Autor Wątek: Unicode na kilku platformach.  (Przeczytany 3097 razy)

Offline dario

  • Użytkownik

# Styczeń 06, 2010, 09:06:45
W nowym projekcie, stanąłem przed zadaniem dodania wsparcia dla Unicode, jak można się domyśleć, do łatwej lokalizacji. I chyba to zadanie mnie przerasta.

Docelowe platformy to Windows, Linux i MacOS, aplikacja pisana jest w C++. W internecie, za wiele na ten temat nie znalazłem. Może skupmy się na dwóch platformach Windows i Linux. W Windows mamy UTF-16 w Linuxie UTF-8. Microsoft dostarcza nam funkcje do manipulacji na szerokich znakach, np. _wfopen, na Linuxie mamy zwykłe fopen, które (chyba) radzi sobie z nazwami i ścieżkami w Unicodzie (UTF-8?). W C++ mamy typ wchar_t ale różni się on w zależności od platformy/kompilatora. Jak to *** ugryźć? Operacje na stringach, plikach itp. Biblioteka standradowa ma typy takie jak std::wfstream, std::wstring, ale wszystkie używają wchar_t którego rozmiar zmienia się na każdej platformie. Chyba jakieś znaczenie to ma. Nie wiem w ogóle za co się złapać. Mógłby mnie ktoś naprowadzić na to, jak dodać wsparcie dla unikodu na tych dwóch platformach? Najlepiej tak, aby nie trzeba było przy portowaniu gry zbyt wiele w tej materii zmieniać ;)

Dodam jeszcze tylko, że gra pisana jest na własnym frameworku, który aktualnie przepisuję pod kątem kilku platform (do tej pory działał tylko na Windows).

Zastanawiałem się już nawet nad porzuceniem tych dwóch mniej znaczących platform. Zakładając że gra jest casualem, na systemy Linuxowe raczej nikt nie wydaje takich gier. Sporą popularnością cieszą się gry na Mac-a. Nie wiem tylko czy praca włożona w pisanie przenośnego kodu się opłaci.

Można też pisać na kilka platform, ale olać sprawę lokalizacji.

Z góry dziękuję za wszelką pomoc.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline agent_J

  • Użytkownik

# Styczeń 06, 2010, 09:12:39
W najprostszym przypadku możesz użyć Qt do tworzenia aplikacji - tam jest pełne wsparcie dla unikodu. Daruj sobie Windows-1250 i temu podobne barachło.



Offline vashpan

  • Użytkownik
    • Strona

# Styczeń 06, 2010, 10:53:05
Moim zdaniem najlepiej zapomniec o tym co dany system oferuje, i napisac wlasna "obsluge" UTF :) Czy to UTF-8 czy UTF-16, whatever. Uzyc potem np. freetype to renderowania tekstu i tyle... Np. SDL i jego SDL_ttf ktory korzysta z UTF-8( i freetype ), w ten sposob dziala, wystarczy miec zrodla zakodowane jako UTF-8 i napisac sobie w kodzie "Zażółć gęślą jaźń" i dla czcionki majaca polskie znaki bedzie smigac :) Do tego jakies utilsy do obslugi UTF-8 i tyle. Jak nie chcesz obcych zaleznosci ( a chyba nie chcesz ) to poczytaj sobie zrodla SDL_ttf i z uzyciem freetype zrob cos podobnego...

Offline Esidar

  • Użytkownik

# Styczeń 06, 2010, 12:14:19
W Windows mamy UTF-16 w Linuxie UTF-8.
W Windows jest i UTF-8 i UTF-16 i UTF-32 i jestem pewny że Linux też to obsługuje.

Możesz używać czegokolwiek bo każdy system i tak sobie z tym poradzi.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Styczeń 06, 2010, 12:21:20
Cytuj
Microsoft dostarcza nam funkcje do manipulacji na szerokich znakach, np. _wfopen, na Linuxie mamy zwykłe fopen, które (chyba) radzi sobie z nazwami i ścieżkami w Unicodzie (UTF-8?).
Tylko po co Ci coś takiego? W grach gracze zwykle nie mają kontroli nad nazwami żadnych plików.

Offline yarpen

  • Użytkownik

# Styczeń 06, 2010, 12:55:13
Cytuj
Microsoft dostarcza nam funkcje do manipulacji na szerokich znakach, np. _wfopen, na Linuxie mamy zwykłe fopen, które (chyba) radzi sobie z nazwami i ścieżkami w Unicodzie (UTF-8?).
Tylko po co Ci coś takiego? W grach gracze zwykle nie mają kontroli nad nazwami żadnych plików.
Ale zeby byc w zgodzie z GFW nalezy robic save'y w MyDocuments.

Offline dario

  • Użytkownik

# Styczeń 06, 2010, 12:58:34
W Windows mamy UTF-16 w Linuxie UTF-8.
W Windows jest i UTF-8 i UTF-16 i UTF-32 i jestem pewny że Linux też to obsługuje.

Możesz używać czegokolwiek bo każdy system i tak sobie z tym poradzi.


Prawda. Problem jest tylko taki, że za pomocą fopen, std::fstream czy też CreateFileA mogę stworzyć plik z nazwą składającą się wyłącznie ze znaków ASCII (0-127). Jeżeli do tych funkcji wrzucę nawet tekst zakodowany jako UTF-8 to otworzenie pliku się nie powiedzie. Aby otworzyć plik który w nazwie ma znaki Unicode, muszę wykorzystać _wfopen, std::wfstream czy CreateFileW (o ile jest coś takiego). Wtedy jako argument wrzucam wchar_t i tekst kodowany jako UTF-16. Jak mogę więc cokolwiek zrobić z funkcjami pod windows, aby akceptowały ciągi znaków w UTF-8? Czegoś nie wiem, czy nie rozumiem? Wiem jedynie że w winapi są funkcje do konwersji pomiędzy różnymi kodowaniami: MultiByteToWideChar i na odwót. W Linuxie tego problemu nie ma. Mam tekst jako UTF-8 czy ASCII wrzucam do zwykłego fopen i reszta się robi sama ;)

Cytuj
Moim zdaniem najlepiej zapomniec o tym co dany system oferuje, i napisac wlasna "obsluge" UTF  Czy to UTF-8 czy UTF-16, whatever.

O tym już myślałem i właśnie zastanawiam się jak to najlepiej zrealizować...

Cytuj
Microsoft dostarcza nam funkcje do manipulacji na szerokich znakach, np. _wfopen, na Linuxie mamy zwykłe fopen, które (chyba) radzi sobie z nazwami i ścieżkami w Unicodzie (UTF-8?).
Tylko po co Ci coś takiego? W grach gracze zwykle nie mają kontroli nad nazwami żadnych plików.


A co np. z edytorem? Powiedzmy że go udostępnię społeczności. W Chinach ktoś może sobie pliki po temtejszemu zapisywać. Jak je wtedy otworzą w edytorze? Zmusić ich do nie używania tego egzotycznego alfabetu? ;)


Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Styczeń 06, 2010, 13:02:37
Cytuj
W Chinach ktoś może sobie pliki po temtejszemu zapisywać.
A może? Jak mu nie pozwolisz, to nie będzie mógł. ;)

Offline Khaine

  • Użytkownik

# Styczeń 06, 2010, 13:43:31
Cytuj
O tym już myślałem i właśnie zastanawiam się jak to najlepiej zrealizować...
napisz wlasna klase string ze znakami typu unsigned short

Offline Liosan

  • Redaktor

# Styczeń 06, 2010, 13:56:35
Cytuj
O tym już myślałem i właśnie zastanawiam się jak to najlepiej zrealizować...
napisz wlasna klase string ze znakami typu unsigned short
e, a może jednak lepiej użyć szablonu basic_string z stla...? :)

Liosan

Offline dario

  • Użytkownik

# Styczeń 06, 2010, 13:59:36
Cytuj
O tym już myślałem i właśnie zastanawiam się jak to najlepiej zrealizować...
napisz wlasna klase string ze znakami typu unsigned short
e, a może jednak lepiej użyć szablonu basic_string z stla...? :)

Liosan

Widziałem coś takiego w źródłach SFML. Niesie to ze sobą jakieś wady?

Offline bies

  • Użytkownik

# Styczeń 06, 2010, 14:39:37
e, a może jednak lepiej użyć szablonu basic_string z stla...? :)
Widziałem coś takiego w źródłach SFML. Niesie to ze sobą jakieś wady?
Tak, basic_string<> nadaje się tylko do znaków o stałej szerokości. I aby uwzględnić chiński musisz użyć UTF-32 co będzie mocno zajmowało pamięć wszędzie poza Chinami. A napisanie klasy do UTF-8 nie jest trywialne. Użyj jakiejś istniejącej, np. z ICU lub glibmm:ustring. Do konwersji możesz użyć albo czegoś dla platformy albo np. przenośnego libiconv.

st3tc

  • Gość
# Styczeń 06, 2010, 14:42:20
Ja bym się na Twoim miejscu zdecydował na jeden standard niezależnie od platformy i po prostu napisał wraperki dla wersji zależnych od OS. I poszedłbym w stronę ... UTF-8 :).
Czyli aplikacja operuje na UTF-8, na windzie odp. klasy dokonują po prostu translacji UTF-8 -> UTF-16 i używają odp. api.

Takie podejście da mi coś jeszcze. Zakładam, że skoro idziesz w unicode to masz zamiar udostępnić możliwość tworzenia nowych wersji językowych. Używając UTF-8 mogę sobie użyć biblioteczki gettext (http://www.gnu.org/software/gettext/)  :). Jej narzędzia same mi wyciągną z kodu stringi do translacji, umożliwiają tworzenie nowych wersji językowych, kompilacje do binarnych zasobów  itp itd.

Offline Patryk N.

  • Użytkownik

# Styczeń 08, 2010, 14:12:39
Jeśli chodzi o system Windows to możesz zerknąć na ten artykuł:
www.codeproject.com/KB/stl/utf8facet.aspx
Powinno to rozwiązać Twoje problemy z kodowaniem na platformie MS.

Co do systemu Linux i MacOSX to na nich robisz wszystko w sposób standardowy, otwierasz plik, wczytujesz wyrazy do wstring i wyświetlasz.

Aha w aplikacji ustaw jeszcze odpowiednią lokalizację, np:
setlocale(LC_ALL,"");

Pozdrawiam Patryk,

Offline dario

  • Użytkownik

# Styczeń 08, 2010, 18:05:49
Cytuj
Ja bym się na Twoim miejscu zdecydował na jeden standard niezależnie od platformy i po prostu napisał wraperki dla wersji zależnych od OS. I poszedłbym w stronę ... UTF-8 .
Czyli aplikacja operuje na UTF-8, na windzie odp. klasy dokonują po prostu translacji UTF-8 -> UTF-16 i używają odp. api.

I tak też zrobiłem. Może trochę na około, bo napisałem klasę UString od podstaw. Ale oprócz masy straconego czasu, wiele się nauczyłem i dodałem kilka elementów, których brakowało mi w std::string.

Wewnętrznie przechowuję dane w UTF-8 i udostępniłem metody do konwersji z UTF-8 na UTF-16 i UTF-32 oraz w drugą stronę. Kto jest zainteresowany algorytmem do konwersji, to są dwa sposoby (dla potomnych;):

http://code.google.com/p/oberfs/source/browse/trunk/ConvertUTF.h?spec=svn10&r=10
http://code.google.com/p/oberfs/source/browse/trunk/ConvertUTF.c?spec=svn10&r=10

Jest jeszcze sposób bez przesunięć bitowych, z dzieleniem i modulo:

http://www1.tip.nl/~t876506/utf8tbl.html

Opisy UTF-8, 16 i 32 są na wikipedii. Tutaj jeszcze trochę info na temat UTF-8:

http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8

Jedyny problem z UTF-8 który mnie martwi to prędkość jego przetwarzania, jako że jest to format o różnej wielkości dla znaków. Ale UTF-16 nie jest pod tym względem lepszy, ponieważ trzeba sprawdzać obecność "surrogate pairs"...Jest jeszcze UCS-2 o stałej szerokości znaków, ale nie obsłuży wszystkich dostępnych. Na UTF-32 szkoda pamięci. Poza tym większość bibliotek open-source działa z kodowaniem UTF-8.

Cytuj
Takie podejście da mi coś jeszcze. Zakładam, że skoro idziesz w unicode to masz zamiar udostępnić możliwość tworzenia nowych wersji językowych. Używając UTF-8 mogę sobie użyć biblioteczki gettext (http://www.gnu.org/software/gettext/)  . Jej narzędzia same mi wyciągną z kodu stringi do translacji, umożliwiają tworzenie nowych wersji językowych, kompilacje do binarnych zasobów  itp itd.

Nie wiedziałem o tym, muszę się temu przyjżeć.

Cytuj
Jeśli chodzi o system Windows to możesz zerknąć na ten artykuł:
www.codeproject.com/KB/stl/utf8facet.aspx
Powinno to rozwiązać Twoje problemy z kodowaniem na platformie MS.

Moje problemy z kodowaniem na tej dziwnej platformie jaką jest Windows są już rozwiązane;) Artykuł widziałem, ale dzięki. Im bardziej zagłębiam się w Linuxa tym bardziej widzę że wszystko jest tam sensowniej zrobione.

Jeszcze raz dziękuję wszystkim za odpowiedzi.