Так, ChangeTextPy более-менее отлажен. Даже удалось решить проблему с Cook - теперь повар это повар, а готовить - это готовить (точнее "Готов" и кусочек буквы "и", но уже не "Пова").
Оказалось, что сделать перевод только на основе ChangeText не получится - кое-где текст начинает обрезаться.
Честно говоря, в коде пока не ковырялся, но не пойму, с чем связано подобное ограничение.
Насколько помню, в версии от mialax'а таких проблем не было. Там алгоритм был примерно такой:
- Считывался весь текст со страницы.
- В считанном тексте проводились замены по словарю
- При необходимости текст форматировался (надо было допиливать)
- Весь текст выводился в окне DF.
1. Исходников модифицированной библиотеки SDL_ttf от mialax'а у меня нет, но могу с 99% уверенностью сказать, что по поводу алгоритма ты ошибаешься.
2. Попробуй с помощью его либы заменить "Пова" на "Готовить" и зайти в z -> кухня. Это не связано с алгоритмом работы, а связано с определением ширины "плашки" (SDL_Surface), на которую выводится текст. Кстати, эту версию нужно будет проверить в дизассемблере, т.к. в SDL я уже потихоньку начинаю разбираться.
...
Исходник я нашел. Под спойлером выдержки из него. Правда, я убрал закомментированный код перевода через онлайн-переводчик.
Спойлер
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool Render = false;
int Cur = 0;
int Cur1 = 0;
Uint16 texts[200][80];
HWND df=NULL;
HRGN rgn = CreateRectRgn(0,0,0,0);
bool KeyNum = false;
bool oldKeyNum = false;
RECT rect;
Uint16 cash_eng[65536][80];
Uint16 cash_rus[65536][80];
#define HESH(t) (((byte)(t[0]))+((Uint16)((byte)(t[1])))*256)
Uint16* TranslRus(Uint16* text, char From)
{
KeyNum = 1;//Control::IsKeyLocked( Keys::NumLock);
if (KeyNum)
{
int leng = wcslen((wchar_t*)text);
bool Small = true;
if (leng > 2)
{
Small = false;
if ( ((text[0])==(70))&&((text[1])==(80))&&((text[2])==(83)))
Small = true;
}
if (!Small)
{
if ((From==0)&&(!Render))
{
////////////////////////////////
int h = HESH(text);
if (memcmp(text, cash_eng[h],leng*2)==0)
{
memcpy(rez, cash_rus[h],sizeof(rez));
text = rez;
}
else
{
////////////////////////////////
memcpy(rez, ChangeText((wchar_t*)text),sizeof(rez));
memcpy(cash_eng[h],text,sizeof(rez));
text = rez;
memcpy(cash_rus[h],rez,sizeof(rez));
}
//////////////////////////////////////
memcpy(texts[Cur],rez,sizeof(rez));
Cur++;
Cur1=0;
}
if ((From==1)&&(!Render))
{
text = texts[Cur1];
}
if ((From==0)&&(Render))
{
text = texts[Cur1];
Cur1++;
Cur = 0;
}
Render = (From == 1);
}
}
return text;
}
int TTF_SizeUNICODE(TTF_Font *font,const Uint16 *text, int *w, int *h)
{
int status;
const Uint16 *ch;
int swapped;
int x, z;
int minx, maxx;
int miny, maxy;
c_glyph *glyph;
FT_Error error;
FT_Long use_kerning;
FT_UInt prev_index = 0;
int outline_delta = 0;
/////////////////////////////////////////////////////////////////////
text = TranslRus((Uint16 *)text, 0);
/////////////////////////////////////////////////////////////////////
...
}
...
SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font,
/* const*/ Uint16 *text, SDL_Color fg)
{
int xstart;
int width, height;
SDL_Surface *textbuf;
Uint32 alpha;
Uint32 pixel;
const Uint16 *ch;
Uint8 *src;
Uint32 *dst;
Uint32 *dst_check;
int swapped;
int row, col;
c_glyph *glyph;
FT_Error error;
FT_Long use_kerning;
FT_UInt prev_index = 0;
////////////////////////////////////mialax
text = TranslRus((Uint16 *)text, 1);
////////////////////////////////////////////
...
}
Смысл такой:
1. DF собирается вывести какой-то текст. Для начала, он обращается к библиотеке SDL_ttf, чтобы узнать какого размера получится текст на экране. Это делается через функцию TTF_SizeUNICODE. Модифицированная библиотека этот текст на входе подменяет, обратившись к функции TranslRus, которая в свою очередь обращается ко внешней функции ChangeText из библиотеки ChangeText.dll. ChangeText при первом вызове грузит словарь из файла, и ищет перевод по нему. Дальше перевод возвращается в функцию TranslRus, которая его сохраняет в хэш-таблицу, чтобы в следуюущий раз при запросе того же текста уже не обращаться в ChangeText (т.н.
кэширование). И дальше уже переведенный текст возвращается в TTF_SizeUNICODE, которая уже возвращает DF размеры переведенного (а не исходного) текста.
2. DF нужно преобразовать нужный текст в изображение. Он обращается к функции TTF_RenderUNICODE_Blended библиотеки SDL_ttf. Модифицированная библиотека его опять же подменяет и в картинку превращается уже не исходный текст, а переведенный. DF как ни в чем ни бывало выводит эту картинку на экран.
Логика моей Fake_ttf примерно та же (подмена выводимого текста), только она служит простым переходником между DF и настоящим SDL_ttf, кроме того передавая текст в ChangeText.dll и из него. Кэширование перевода можно организовать внутри ChangeText.dll. Получилось довольно просто и надежно, и не нужно заморачиваться с компиляцией SDL_ttf.dll.