Fix #647 sf::Image support for Unicode filenames save/load#3403
Merged
ChrisThrasher merged 2 commits intoJan 30, 2025
Conversation
ChrisThrasher
requested changes
Jan 29, 2025
learn-more
reviewed
Jan 29, 2025
5 tasks
6be70ee to
d6c8002
Compare
7538f71 to
2aa3801
Compare
kimci86
reviewed
Jan 30, 2025
2aa3801 to
8894b9e
Compare
8894b9e to
7d828d5
Compare
ChrisThrasher
approved these changes
Jan 30, 2025
sf::Image support for Unicode filenames save/load
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Here's a fix issue #647
All the tests have passed on https://github.com/FRex/SFML/actions/runs/13015976076
It has
3commits (for explanation of each see below):sf::Imagesaving/loading to/from Unicode filenames.1. fix for printingstd::filesystem::pathtostd::stringto then print error tosf::err().EDIT: The last commit from above was put in PR #3407 and merged, now this PR has jus
sf::Imagetests and fixes for Unicode load/save filenames.The tests check for 4 different interesting Unicode filenames: one with a Spanish letter, one with a Polish letter, one with a CJK character, and one with an emoji.
The Spanish letter is a Latin 1 character, and often works on Windows due to codepage 850 aka Latin 1 (which has values that overlap with Unicode, by design) being set. The Polish character will fail with that codepage since it's above
0xff. The CJK character will not work in any of these extended ASCII/codepage settings, it requires real Unicode support to work.The emoji makes sure characters above
0xffff(outside of Unicode's first plane, the Basic Multilingual Plane) are handled properly. These characters take 3 UTF-8 bytes/codeunits or 2 wchars/UTF-16 codeunits (using surrogate pairs). Some older software (especially made before emojis became so popular online) sometimes fails on them, if they assume that UTF-16 is fixed width, so this is a good test for robust Unicode handling.The fix in
sf::Imageusesstd::ifstream/std::ofstreamwhich acceptstd::filesystem::pathso the Unicode stuff never leavesstd::parts,stb_/stbi_then use callbacks to read to/from these streams, just how SFML's own streams.EDIT: see above, this commit is no longer in this PR.
InUtils.cppthere is a helper function for making error messages that putsstd::filesystem::pathinto acharstream, which throws an exception on Windows if that path contains Unicode. The fix is to always convert to UTF-8. Thereinterpret_castis because in C++17u8pathischarstring, but in C++20 it'schar8_tstring which cannot be put into acharstream. It's same data andchar8_tis same size ascharso it works.Tasks
How to test this PR?
Run the below program on Windows and see that files
🐌.png,日.png,ń.pngandñ.pngappear and load, as expected, and error message is printed properly in UTF-8 (if redirected to file) or at least doesn't throw an exception and just has some boxy characters in place of Unicode (if in default terminal).Before this PR due to using
.string()all these operations would throw a "No mapping for the unicode character exists in the target multi-byte code page" exception when path contains Unicode outside of current codepage (so most likelyñworks, but the other three don't, for most Western/American developers on default English language Windows).