Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FT_Exception: (cannot open resource) #157

Open
moi15moi opened this issue Jul 12, 2022 · 21 comments · May be fixed by #177
Open

FT_Exception: (cannot open resource) #157

moi15moi opened this issue Jul 12, 2022 · 21 comments · May be fixed by #177

Comments

@moi15moi
Copy link

moi15moi commented Jul 12, 2022

freetype.Face() seems to not take non-ascii path. It will raise an exception.

With a string path

import freetype
font = freetype.Face(r"C:\Windows\Fonts\حُرّ عادي.ttf") # it return: freetype.ft_errors.FT_Exception: FT_Exception:  (cannot open resource)

With an BufferedReader

from pathlib import Path
import freetype
font = freetype.Face(Path(r"C:\Windows\Fonts\حُرّ عادي.ttf").open("rb")) # Works
@HinTak
Copy link
Collaborator

HinTak commented Jul 13, 2022

Try C:\\Windows\\Fonts\\حُرّ عادي.ttf (double backslash) or "C:/Windows/Fonts/حُرّ عادي.ttf". This is likely a Windows IO anomaly.

@moi15moi
Copy link
Author

I try the two method you have suggest. Both of them give me the same exception.

freetype.Face("C:\\Windows\\Fonts\\حُرّ عادي.ttf")
freetype.Face("C:/Windows/Fonts/حُرّ عادي.ttf")

@rougier
Copy link
Owner

rougier commented Jul 14, 2022

Can you print here what is Path(r"C:\Windows\Fonts\حُرّ عادي.ttf")?

@moi15moi
Copy link
Author

It print me this (so the exact same thing that I provide): C:\Windows\Fonts\حُرّ عادي.ttf

@rougier
Copy link
Owner

rougier commented Jul 15, 2022

Is is a PosixPath ?

@moi15moi
Copy link
Author

No, simply a path.

It will instanciate a windows path since I am on windows: https://docs.python.org/3/library/pathlib.html

@HinTak
Copy link
Collaborator

HinTak commented Jul 15, 2022

AFAIK it needs to be something acceptable to windows' c runtime's fopen().

Python 3 is unicode internally and needs some encoding on all platforms. Unix's takes utf8, while some windows internal bits are utf16. You might be able to experiment by playing with python ctypes on Windows directly. I am afraid this is one area where playing with wine does not help, and wine differs slightly in behavior compared to windows. Ie running windows python on wine is no help.

@rougier
Copy link
Owner

rougier commented Jul 15, 2022

@HinTak We could use pathlib internally and we would be on the safe side, no?

@HinTak
Copy link
Collaborator

HinTak commented Jul 15, 2022

@rougier yes, apparently it is included in python standard library since 3.4 (and we had a separate frozen-ish 2.x branch). If anybody cares enough about older 3.x, they should do their own thing and/or submit a pull.

That said, we really want to know why it doesn't work on Windows with non-ascii paths. The "/" vs "" (and needing to double "\" or switch to "/") is relatively well known. Win32 IO have ascii vs unicode IO routines, but I don't think freetype uses those.

Thinking about it, @moi15moi , where did you get your libfreetype.dll? I am wondering if msvc compiled ones uses the win32 routines. I am quite sure mingw built ones don't.

@moi15moi
Copy link
Author

Thinking about it, @moi15moi , where did you get your libfreetype.dll? I am wondering if msvc compiled ones uses the win32 routines. I am quite sure mingw built ones don't.

I don't know what you are talking about. I just install freetype-py like this: pip install freetype-py

@HinTak
Copy link
Collaborator

HinTak commented Jul 15, 2022

@moi15moi argh, sorry somebody else among the team did the bundled binaries. According to https://pypi.org/project/freetype-py/#description , it is probably msvc (=visual studio) + cmake -built.

@rougier
Copy link
Owner

rougier commented Jul 16, 2022

I agree it would be good to know why it fails. See also https://jod.al/2019/12/10/pathlib-and-paths-with-arbitrary-bytes/

@HinTak
Copy link
Collaborator

HinTak commented Jul 20, 2022

I was just reminded of a somewhat similar issue in a different project I work on:
Robmaister/SharpFont#89
File names go through two translation processes, one as it crosses the non-C / C boundary (in both cases, the non-C sides are widows-based and uses UTF16). Then between freetype and the file-system. There workaround there was to read the file in full in memory on the non-C side, and passes the whole block of memory to freetype. (We never "solved" it, just found a workaround and moved on...)

The two questions are mainly what bytes as a file name FreeType receives, and can one open a file with those bytes via fopen.

@rougier
Copy link
Owner

rougier commented Jul 25, 2022

Can't we use the pathlib library to solve the translation problem for us then?

@cd-86
Copy link

cd-86 commented Sep 13, 2022

I encountered the same problem, and it was solved by changing the encoding of line 162 of freetype/init.py to ansi

def _encode_filename(filename):
    # encoded = filename.encode(sys.getfilesystemencoding())
    encoded = filename.encode('ansi')
    if "?" not in filename and b"?" in encoded:
        # A bug, decoding mbcs always ignore exception, still isn't fixed in Python 2,
        # view http://bugs.python.org/issue850997 for detail
        raise UnicodeError()
    return encoded

@moi15moi
Copy link
Author

This is not a good idea.

@moi15moi
Copy link
Author

@rougier Have you found any alternative?

@moi15moi
Copy link
Author

I just found this issue: https://gitlab.freedesktop.org/freetype/freetype/-/issues/1098
This may help you

@HinTak
Copy link
Collaborator

HinTak commented Aug 17, 2023

No, you did not notice the "won't fix" label on the issue you referenced. :-).

@moi15moi
Copy link
Author

moi15moi commented Aug 18, 2023

Exactly. Then, when the font filename contain an non ascii char and the platform is windows, we could simply create a memory font.

@HinTak
Copy link
Collaborator

HinTak commented Aug 18, 2023

Not sure what you are asking for. It is the same as what you did, freetype.Face(Path(r"C:\Windows\Fonts\حُرّ عادي.ttf").open("rb")), creating a memory font. This is pretty much how the sharpfont solution works too, just read it via the non-C way, then passes the block of memory to the c-side to freetype.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants