Example #1
0
def _makeTTFragments_delta(delta, relSet):
    """
    Returns a Hints object containing a fragment of TrueType code designed to
    add the specified delta to the stack elements at the positions noted in the
    relSet (whose length will always be greater than one; if there is only one
    value, the client should call _makeTTFragment_delta instead).
    
    >>> _makeTTFragments_delta(20, set([-1, -3]))
    [PUSH [3], MINDEX, PUSH [20], ADD, PUSH [3], MINDEX, PUSH [3], MINDEX, PUSH [20], ADD]
    >>> _makeTTFragments_delta(20, set([-2, -4]))
    [PUSH [4], MINDEX, PUSH [20], ADD, PUSH [4], MINDEX, PUSH [4], MINDEX, PUSH [20], ADD, PUSH [4], MINDEX]
    """
    
    lowest = min(relSet)
    _p = opcode_tt.Opcode_push([-lowest])
    _delta = opcode_tt.Opcode_push([delta])
    v = []
    
    while lowest < 0:
        v.extend([_p, _mindexOpcode])
        
        if lowest in relSet:
            v.extend([_delta, _addOpcode])
        
        lowest += 1
    
    return hints_tt.Hints(v)
Example #2
0
def _makeTTFragment_call(fdefSet, fdefMap):
    """
    Returns a Hints object containing a fragment of TrueType code designed to
    map any value in fdefSet into the corresponding value in fdefMap. Note that
    idempotent mappings do not result in any TrueType code.
    
    If no changes need to be made, None is returned.
    """
    
    # First determine which functions actually need to be altered.
    needMap = dict((fIn, fOut) for fIn, fOut in fdefMap.items() if fIn in fdefSet if fIn != fOut)
    
    if not needMap:
        return None
    
    # Now generate the code
    H = hints_tt.Hints
    
    if len(needMap) == 1:
        # for a single map, just add the difference
        fIn, fOut = needMap.popitem()
        _delta = opcode_tt.Opcode_push([fOut - fIn])
        return H([_delta, _addOpcode])
    
    stillToDo = len(needMap)
    v = []
    
    for fIn, fOut in needMap.items():
        stillToDo -= 1
        _trial = opcode_tt.Opcode_push([fIn])
        _delta = opcode_tt.Opcode_push([fOut - fIn])
        v.extend([_dupOpcode, _trial, _eqOpcode, _ifOpcode, _delta, _addOpcode])
        
        if stillToDo:
            v.append(_elseOpcode)
    
    v.extend([_eifOpcode] * len(needMap))
    return H(v)
def _makePiece_setOneConstant(storeIndex, constant):
    """
    Returns hints to set the storage index to the constant.
    
    (starting stack)    ***
    PUSH                ***  storeIndex  constant
    WS                  ***
    
    >>> print(_makePiece_setOneConstant(20, 4))
    [PUSH [20, 4], WS]
    """

    _push = opcode_tt.Opcode_push([storeIndex, constant])
    return [_push, _wsOpcode]
    def _addSynthCall(self, hString, which, isAACase):
        """
        Given a hint string (which might be potentially empty), adds a call to
        self.synthFDEFIndex to the beginning, integrating with existing PUSHes,
        if present, to make the addition as small as possible. If isAACase is
        True, and the hint string is empty, adds an explicit AA 0 after the
        synth call.
        
        Returns the augmented hint string.
        """

        if hString:
            h = hints_tt.Hints.frombytes(hString)

            if not h[0].isPush():
                _push = opcode_tt.Opcode_push([which, self.synthFDEFIndex])
                return hints_tt.Hints([_push, _callOpcode] + h).binaryString()

            for i, op in enumerate(h):
                if not op.isPush():
                    break

            # i is first non-push, so add values to h[i-1] push

            h[i - 1] = opcode_tt.Opcode_push(h[i - 1].data +
                                             (which, self.synthFDEFIndex))
            h.insert(i, _callOpcode)

        elif isAACase:
            _push = opcode_tt.Opcode_push([0, which, self.synthFDEFIndex])
            h = hints_tt.Hints([_push, _callOpcode, _aaOpcode])

        else:
            _push = opcode_tt.Opcode_push([which, self.synthFDEFIndex])
            h = hints_tt.Hints([_push, _callOpcode])

        return h.binaryString()
def _makePiece_dupOne(storeIndex):
    """
    Returns hints to copy the top stack value thus:
    
    (starting stack)    a
    PUSH                a  storeIndex  2
    CINDEX              a  storeIndex  a
    WS                  a
    
    >>> print(_makePiece_dupOne(20))
    [PUSH [20, 2], CINDEX, WS]
    """

    _push = opcode_tt.Opcode_push([storeIndex, 2])
    return [_push, _cindexOpcode, _wsOpcode]
def _makePiece_dupSkipOne(storeIndex):
    """
    Returns hints to copy the second-from-the-top stack value thus:
    
    (starting stack)    a  ignore
    PUSH                a  ignore  storeIndex  3
    CINDEX              a  ignore  storeIndex  a
    WS                  a  ignore
    
    >>> print(_makePiece_dupSkipOne(20))
    [PUSH [20, 3], CINDEX, WS]
    """

    _push = opcode_tt.Opcode_push([storeIndex, 3])
    return [_push, _cindexOpcode, _wsOpcode]
Example #7
0
def _makeTTFragment_delta(delta, relStack):
    """
    Returns a Hints object containing a fragment of TrueType code designed to
    add the specified delta to the stack element at the relStack position.
    
    >>> _makeTTFragment_delta(20, -1)
    [PUSH [20], ADD]
    >>> _makeTTFragment_delta(20, -2)
    [SWAP, PUSH [20], ADD, SWAP]
    >>> _makeTTFragment_delta(20, -3)
    [ROLL, PUSH [20], ADD, ROLL, ROLL]
    >>> _makeTTFragment_delta(20, -4)
    [PUSH [4], MINDEX, PUSH [20], ADD, PUSH [4], MINDEX, PUSH [4], MINDEX, PUSH [4], MINDEX]
    """
    
    H = hints_tt.Hints
    _delta = opcode_tt.Opcode_push([delta])
    
    if relStack == -1:
        # top of stack is easy case; just PUSH and ADD
        return H([_delta, _addOpcode])
    
    if relStack == -2:
        return H([_swapOpcode, _delta, _addOpcode, _swapOpcode])
    
    if relStack == -3:
        return H([_rollOpcode, _delta, _addOpcode, _rollOpcode, _rollOpcode])
    
    # if we get here, the element to be changed is very deep, so we handle it
    # in a generic way
    
    _count = opcode_tt.Opcode_push([-relStack])
    
    v = [_count, _mindexOpcode, _delta, _addOpcode]
    v.extend([_count, _mindexOpcode] * (-relStack - 1))
    return H(v)
def _makePiece_setTwoConstants(storeIndex, constant1, constant2):
    """
    Returns hints to set storeIndex to constant1 and storeIndex+1 to constant2.
    
    (starting stack)    ***
    PUSH                ***  storeIndex+1  constant2  storeIndex  constant
    WS                  ***  storeIndex+1  constant2
    WS                  ***
    
    >>> print(_makePiece_setTwoConstants(20, 4, 1))
    [PUSH [21, 1, 20, 4], WS, WS]
    """

    _push = opcode_tt.Opcode_push(
        [storeIndex + 1, constant2, storeIndex, constant1])
    return [_push, _wsOpcode, _wsOpcode]
def _makePiece_dupOneSetOne(storeIndex, constant):
    """
    Returns hints that store the specified constant in storeIndex and
    duplicates the top of the stack into storeIndex + 1.
    
    (starting stack)    a
    PUSH                a  storeIndex+1  3  storeIndex  constant
    WS                  a  storeIndex+1  3
    CINDEX              a  storeIndex+1  a
    WS                  a
    
    >>> print(_makePiece_dupOneSetOne(20, 1))
    [PUSH [21, 3, 20, 1], WS, CINDEX, WS]
    """

    _push = opcode_tt.Opcode_push([storeIndex + 1, 3, storeIndex, constant])
    return [_push, _wsOpcode, _cindexOpcode, _wsOpcode]
def _makePiece_dupTwo(storeIndex):
    """
    Returns hints to copy the top two stack values thus:
    
    (starting stack)    a  b
    PUSH                a  b  storeIndex  2  storeIndex+1  5
    CINDEX              a  b  storeIndex  2  storeIndex+1  a
    WS                  a  b  storeIndex  2
    CINDEX              a  b  storeIndex  b
    WS                  a  b
    
    Note if storeIndex+1 doesn't fit in one byte, this effect might be able
    to be done in fewer hint bytes by single pushes and swaps.
    
    >>> print(_makePiece_dupTwo(20))
    [PUSH [20, 2, 21, 5], CINDEX, WS, CINDEX, WS]
    """

    _push = opcode_tt.Opcode_push([storeIndex, 2, storeIndex + 1, 5])
    return [_push, _cindexOpcode, _wsOpcode, _cindexOpcode, _wsOpcode]
Example #11
0
    def buildBinary(self, w, **kwArgs):
        """
        Adds the binary content for the Fpgm object to the specified writer.
        
        >>> utilities.hexdump(_testingValues[1].binaryString())
               0 | B119 022C B201 0203  502D 2C00 012D      |...,....P-,..-  |
        """

        if 'stakeValue' in kwArgs:
            stakeValue = kwArgs.pop('stakeValue')
            w.stakeCurrentWithValue(stakeValue)
        else:
            stakeValue = w.stakeCurrent()

        keysObj = opcode_tt.Opcode_push(sorted(self, reverse=True))
        w.addString(keysObj.binaryString())
        op_ENDF = common.nameToOpcodeMap["ENDF"]
        op_FDEF = common.nameToOpcodeMap["FDEF"]

        for key in sorted(self):
            w.add("B", op_FDEF)
            w.addString(self[key].binaryString())
            w.add("B", op_ENDF)