Font file loaded from temp file seems incorrect

2019-08-05 09:15发布

for key in fnt.keys():

    str1 = base64.b64decode(fnt[key])
    strA = XOR(str1, coder)

    temp = tempfile.TemporaryFile()
    temp.seek(0)
    temp.write(strA)
    temp.seek(0)

    if key == "calibri.ttf":
        FONT = temp
    if key == "calibrib.ttf":
        FONTB = temp
        temp.close()
return (FONT, FONTB)

In the above code I have retrieved fonts saved as a string in a dictionary. When I use this code it returns an error - RuntimeError: Can't seek in stream. With the code below it works perfectly. Someone please explain how to use the temp file method to get the fonts rather than write to file. Is that possible?

for key in fnt.keys():

    str1 = base64.b64decode(fnt[key])
    strA = XOR(str1, coder)

    with open(home + "\\" + key, "wb") as to_disk:
        to_disk.write(strA)
        FONT = "calibri.ttf"
        FONTB = "calibrib.ttf"

return (FONT, FONTB)

I am adding the full code below. See if this helps in giving me a viable answer.

import string
import base64
import os
from fnt import fnt
import string
import tempfile
from itertools import cycle, izip

def XOR(message, key):
    cryptedMessage = ''.join(chr(ord(c)^ord(k)) for c,k in izip(message, cycle(key)))

    return cryptedMessage

#----------------------------------------------------------------------
def main():
    """extracts and returns the font files from fnt.py"""
    coder ="PHdzDER+@k7pcm!LX8gufh=y9A^UaMsn-oW6"
    home = os.getcwd()
    for key in fnt.keys():

        str1 = base64.b64decode(fnt[key])
        strA = XOR(str1, coder)

        #temp = tempfile.TemporaryFile()
        #temp.seek(0)
        #temp.write(strA)
        #temp.seek(0)


        #if key == "calibri.ttf":
            #FONT = temp

        #if key == "calibrib.ttf":
            #FONTB = temp


        with open(home + "\\" + key, "wb") as to_disk:
            to_disk.write(strA)
            FONT = "calibri.ttf"
            FONTB = "calibrib.ttf"

    return (FONT, FONTB)

if __name__=='__main__':
    main()

标签: python pygame
1条回答
ら.Afraid
2楼-- · 2019-08-05 09:56

When temp is closed it is destroyed, so you won't be able to read from it to extract the font data.

On what line of your code do you get the RuntimeError: Can't seek in stream error message? As Michael Petch said, we need to know your OS. tempfile.TemporaryFile() is certainly seekable on Linux.

BTW, in

if key == "calibrib.ttf":
    FONTB = temp
    temp.close()

The temp.close() is inside the if block. I guess that might just be a copy & paste error. But as I said above, you don't want to close these files until you've read from them.

Presumably, your original font reading function opens the font files from disk with the filenames and then accesses the font data using the file handle from open(). So as Michael Petch said, you need to change that to accept handles from files that are already open.

EDIT

I got confused earlier when you said that "There is NO other font reading function", since I couldn't figure out what you were actually trying to do with the decrypted font data.

And I guess I also got confused by you calling your font extraction function main(), since main() is conventionally used as the entry-point into a program, so a program normally doesn't run a bunch of different main() functions in different modules.

Anyway...

I've never used pygame, but from a quick look at the docs you can give pygame.font.Font() either a font name string or an open font filehandle as the first arg, eg

myfont = pygame.font.Font(font_filehandle, size)

Presumably your fnt module has a dict containing two strings of base64 encoded, XOR-encrypted font data, keyed by the font names, "calibrib.ttf".

So this should work, assuming I'm not misunderstanding that pygame doc. :)

Warning: Untested code

def xor_str(message, key):
    return ''.join([chr(ord(c)^ord(k)) for c,k in izip(message, cycle(key))])

def decode_fonts(fnt):
    coder = "PHdzDER+@k7pcm!LX8gufh=y9A^UaMsn-oW6"

    font_fh = {}
    for key in fnt.keys():
        xorfont = base64.b64decode(fnt[key])

        temp = tempfile.TemporaryFile()
        temp.write(xor_str(xorfont, coder))
        temp.seek(0)

        font_fh[key] = temp
    return font_fh

#...............

    #In your pygame function:
    font_fh = decode_fonts(fnt)

    font_obj = {}
    for key in font_fh.keys():
        font_obj[key] = pygame.font.Font(font_fh[key], point_size)

    #Now you can do
    surface = font_obj["calibri.ttf"].render(text, antialias, color, background=None)
查看更多
登录 后发表回答