2010-11-25 59 views
0

J'ai trouvé ce script attaché à a thread in the fontforge-users mailing list. Il fait exactement ce que je veux. Cependant, il semble que pour travailler sur les systèmes 32 bits, et je voudrais vraiment l'utiliser sur mon système 64 bits.aide pour convertir python ctypes struct en 64bit

J'ai fait un peu de lecture mais je n'arrive pas à comprendre comment je devrais modifier ce script (probablement le code?) Pour le faire fonctionner sous une architecture 64 bits. Quelqu'un peut-il aider?

À la votre!

#!/usr/bin/python 
# vim:ts=8:sw=4:expandtab:encoding=utf-8 
# Export named font from PDF file using fontforge and ctypes 

import sys 
from ctypes import * 

STRING = c_char_p 
real = c_longdouble 

# We need the `map` attribute of SplineFont, so declear an incomplete struct. 
# see: http://sourceforge.net/projects/wqy/files/misc/ 
# file: fontforge-bindctypes-0.1.tar.bz2 
class splinefont(Structure): 
    pass 
SplineFont = splinefont 
splinefont._fields_ = [ 
    ('fontname', STRING), 
    ('fullname', STRING), 
    ('familyname', STRING), 
    ('weight', STRING), 
    ('copyright', STRING), 
    ('filename', STRING), 
    ('defbasefilename', STRING), 
    ('version', STRING), 
    ('italicangle', real), 
    ('upos', real), 
    ('uwidth', real), 
    ('ascent', c_int), 
    ('descent', c_int), 
    ('uniqueid', c_int), 
    ('glyphcnt', c_int), 
    ('glyphmax', c_int), 
    ('glyphs', POINTER(c_void_p)), 
    ('changed', c_uint, 1), 
    ('changed_since_autosave', c_uint, 1), 
    ('changed_since_xuidchanged', c_uint, 1), 
    ('display_antialias', c_uint, 1), 
    ('display_bbsized', c_uint, 1), 
    ('dotlesswarn', c_uint, 1), 
    ('onlybitmaps', c_uint, 1), 
    ('serifcheck', c_uint, 1), 
    ('issans', c_uint, 1), 
    ('isserif', c_uint, 1), 
    ('hasvmetrics', c_uint, 1), 
    ('loading_cid_map', c_uint, 1), 
    ('dupnamewarn', c_uint, 1), 
    ('encodingchanged', c_uint, 1), 
    ('multilayer', c_uint, 1), 
    ('strokedfont', c_uint, 1), 
    ('new', c_uint, 1), 
    ('compacted', c_uint, 1), 
    ('backedup', c_uint, 2), 
    ('use_typo_metrics', c_uint, 1), 
    ('weight_width_slope_only', c_uint, 1), 
    ('save_to_dir', c_uint, 1), 
    ('head_optimized_for_cleartype', c_uint, 1), 
    ('ticked', c_uint, 1), 
    ('internal_temp', c_uint, 1), 
    ('complained_about_spiros', c_uint, 1), 
    ('use_xuid', c_uint, 1), 
    ('use_uniqueid', c_uint, 1), 
    ('fv', c_void_p), 
    ('metrics', c_void_p), 
    ('uni_interp', c_int), 
    ('for_new_glyphs', c_void_p), 
    ('map', c_void_p), 
    # ... 
] 

def main(): 
    if len(sys.argv) != 3: 
     print "Usage: %s doc.pdf fontname" % sys.argv[0] 
     sys.exit(2) 
    pdfname = sys.argv[1] 
    fontname = sys.argv[2] 
    fontfile = fontname + '.ttf' 

    # ctypes functions 
    libc = CDLL("libc.so.6") 
    libc.fopen.restype = c_void_p 
    libc.fopen.argtype = [c_char_p, c_char_p] 

    lib_ff = CDLL('libfontforge.so.1') 

    # SplineFont *_SFReadPdfFont(FILE *pdf,char *filename, 
    #  char *select_this_font, enum openflags openflags) 
    lib_ff._SFReadPdfFont.argtypes = [c_void_p, c_char_p, c_char_p, c_int] 
    lib_ff._SFReadPdfFont.restype = POINTER(SplineFont) 

    # int GenerateScript(SplineFont *sf, char *filename, char *bitmaptype, 
    #  int fmflags, int res, char *subfontdefinition, struct sflist *sfs, 
    #  EncMap *map, NameList *rename_to,int layer) 
    lib_ff.GenerateScript.argytpes = [POINTER(SplineFont), c_char_p, c_char_p, 
      c_int, c_int, c_char_p, c_void_p, c_void_p, c_void_p, c_int] 
    lib_ff.GenerateScript.restype = c_int 

    # need to somehow initialize libfontforge or it will segfault somewhere. 
    lib_ff.doinitFontForgeMain() 
    fobj = libc.fopen(pdfname, "rb") 
    if not fobj: 
     print "%s not found" % pdfname 
     sys.exit(1) 

    font = lib_ff._SFReadPdfFont(fobj, pdfname, fontname, 0) 
    ret = 0 
    if bool(font): 
     ret = lib_ff.GenerateScript(font, fontfile, None, -1, -1, None, None, 
       font.contents.map, None, 1) 
    if ret: 
     print 'Font export to "%s".' % fontfile 
    else: 
     print "** Error ** Failed to export font!!" 

if __name__ == '__main__': 
    main() 
+0

Pourquoi quelqu'un a-t-il codé ceci en Python? C'est l'une des rares choses que j'aurais fait en C. –

+0

@Sven Marnach - Je peux voir votre point de vue. De mon point de vue, je cherche un moyen d'appeler cela à partir d'un script python plus compliqué, donc cette approche, si je peux le faire fonctionner, me plaît. Si j'étais capable de réécrire cela en C, je serais ouvert à cela, mais je suppose que je devrais encore faire face au même problème d'architecture? – simon

+0

Je ne vois pas la raison d'un problème 64 bits, ni dans le code Python ci-dessus, ni dans le recodage en C. Mais la version C de ce script serait vraiment courte. Vous pouvez l'appeler à partir de Python en tant que sous-processus ou via des ctypes. –

Répondre

2

La question est de savoir si FONTFORGE_CONFIG_USE_LONGDOUBLE est défini ou non /usr/include/fontforge/config.h. Si elle est définie, la définition du code est correcte. Sur mon amd64 installation de linux, ni FONTFORGE_CONFIG_USE_LONGDOUBLE ni FONTFORGE_CONFIG_USE_DOUBLE sont définis, donc je besoin de changer

real = c_float 

Avec ce changement, il fonctionne très bien.

+0

Merci beaucoup pour votre réponse, mais je ne peut pas répliquer vos résultats! Sur mon installation (64bit Ubuntu 10.10), ni 'FONTFORGE_CONFIG_USE_LONGDOUBLE' ni' FONTFORGE_CONFIG_USE_DOUBLE' ne sont définis dans '/ usr/include/fontforge/config.h', mais changer la définition de' real' en 'c_float' aboutit toujours à un segfault. Pourrait-il être autre chose (trop)? – simon

+0

Pour une analyse plus approfondie, vous devrez fournir un fichier PDF spécifique et une invocation spécifique. Je ne peux pas penser à autre chose qui pourrait causer le problème. –

+0

Merci pour votre réponse. Si vous êtes prêt à regarder, j'ai posté mon pdf de test ici (http://simonwiles.net/test_fore.pdf) - c'est juste la première chose multilingue que j'avais à portée de main, pour tester. Il ne contient que deux polices (PMingLiu et Gentium), et le script est capable de les extraire sur des systèmes 32 bits avec les invocations 'python ff_font_extract.py test_fore.pdf BAAAAA + Gentium' et' python ff_font_extract.py test_fore.pdf CAAAAA + PMingLiU' . Puis-je vous demander quelle est la distribution Linux 64 bits sur laquelle vous avez travaillé? (ps. - J'apprécie grandement votre serviabilité!) – simon