void ReCreateMenuLanguageEntryLinks() { // удаляем все симлинки текстур vw_DeleteEntryLinkVFS("DATA/GAME/mission.tga"); vw_DeleteEntryLinkVFS("DATA/GAME/missionfailed.tga"); vw_DeleteEntryLinkVFS("DATA/GAME/pause.tga"); vw_DeleteEntryLinkVFS("DATA/MENU/button_weaponry_in.tga"); vw_DeleteEntryLinkVFS("DATA/MENU/button_weaponry_out.tga"); // создаем новые симлинки CreateMenuLanguageEntryLinks(); // если текстура была загружена - выгружаем, и загружаем по новой if (vw_FindTextureByName("DATA/GAME/mission.tga")) { vw_ReleaseTexture(vw_FindTextureByName("DATA/GAME/mission.tga")); vw_SetTextureAlpha(0.0f, 0.0f, 0.0f); vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_EQUAL, false); vw_LoadTexture("DATA/GAME/mission.tga", NULL, true); } if (vw_FindTextureByName("DATA/GAME/missionfailed.tga")) { vw_ReleaseTexture(vw_FindTextureByName("DATA/GAME/missionfailed.tga")); vw_SetTextureAlpha(0.0f, 0.0f, 0.0f); vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_EQUAL, false); vw_LoadTexture("DATA/GAME/missionfailed.tga", NULL, true); } if (vw_FindTextureByName("DATA/GAME/pause.tga")) { vw_ReleaseTexture(vw_FindTextureByName("DATA/GAME/pause.tga")); vw_SetTextureAlpha(0.0f, 0.0f, 0.0f); vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_EQUAL, false); vw_LoadTexture("DATA/GAME/pause.tga", NULL, true); } if (vw_FindTextureByName("DATA/MENU/button_weaponry_in.tga")) { vw_ReleaseTexture(vw_FindTextureByName("DATA/MENU/button_weaponry_in.tga")); vw_SetTextureAlpha(0.0f, 0.0f, 0.0f); vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, false, TX_ALPHA_EQUAL, false); vw_LoadTexture("DATA/MENU/button_weaponry_in.tga", NULL, false); } if (vw_FindTextureByName("DATA/MENU/button_weaponry_out.tga")) { vw_ReleaseTexture(vw_FindTextureByName("DATA/MENU/button_weaponry_out.tga")); vw_SetTextureAlpha(0.0f, 0.0f, 0.0f); vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, false, TX_ALPHA_EQUAL, false); vw_LoadTexture("DATA/MENU/button_weaponry_out.tga", NULL, false); } }
//------------------------------------------------------------------------------------ // загрузка и генерация всех необходимых данных для символа (utf32) //------------------------------------------------------------------------------------ eFontChar* vw_LoadFontChar(unsigned UTF32) { // устанавливаем размеры if (FT_Set_Char_Size( InternalFace, InternalFontSize <<6, InternalFontSize <<6, 96, 96 )) { fprintf(stderr, "Can't set char size %i.", InternalFontSize); return 0; } // загрузка глифа нужного нам символа if (FT_Load_Char( InternalFace, UTF32, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT)) { fprintf(stderr, "Can't load Char: %u\n", UTF32); return 0; } // создаем структуру FontChar eFontChar* NewChar; NewChar = new eFontChar; NewChar->UTF32 = UTF32; NewChar->CharTexture = 0; NewChar->FontSize = InternalFontSize; NewChar->TexturePositionLeft = 0; NewChar->TexturePositionRight = InternalFace->glyph->bitmap.width; // в случае одной текстуры совпадают с шириной NewChar->TexturePositionTop = 0; NewChar->TexturePositionBottom = InternalFace->glyph->bitmap.rows; // в случае одной текстуры совпадают с высотой NewChar->Width = InternalFace->glyph->bitmap.width; NewChar->Height = InternalFace->glyph->bitmap.rows; NewChar->Left = InternalFace->glyph->bitmap_left; NewChar->Top = InternalFace->glyph->bitmap_top; NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f; NewChar->Prev = 0; NewChar->Next = 0; BYTE * pixels; pixels = new BYTE[NewChar->Width*NewChar->Height*4]; // битмап идет в 1 канале градаций серого, делаем 32бита rgba int k=0; BYTE ColorRGB[3]={255,255,255}; for (int j=0; j<NewChar->Height; j++) { for (int i=0; i<NewChar->Width; i++) { // RGB составляющую заполняем белым memcpy(pixels + k, ColorRGB, 3); k+=3; memcpy(pixels + k, InternalFace->glyph->bitmap.buffer+(NewChar->Height-j-1)*NewChar->Width+i, 1); k++; } } // называем текстуру номером символа в утф32 char texturefilename[MAX_PATH]; sprintf(texturefilename, "%i", UTF32); vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false); NewChar->CharTexture = vw_CreateTextureFromMemory(texturefilename, pixels, NewChar->Width, NewChar->Height, 4, false, 0, 0, false); // очищаем память delete [] pixels; // подключаем к менеджеру vw_AttachFontChar(NewChar); return NewChar; }
//----------------------------------------------------------------------------- // делаем генерацию нужных символов по списку генерируя одну текстуру //----------------------------------------------------------------------------- void vw_GenerateFontChars(int FontTextureWidth, int FontTextureHeight, const char * CharsList) { printf("Font characters generation start.\n"); // будем использовать последовательность как имя текстуры const char *TextureName = CharsList; // временный массив BYTE * DIB; DIB = new BYTE[FontTextureWidth*FontTextureHeight*4]; // всегда делаем rgba // устанавливаем 0 везде, чтобы потом не краcить rgb, а только формировать альфу memset(DIB, 0, FontTextureWidth*FontTextureHeight*4); // данные для работы с вклеиванием в текстуру int CurrentDIBX = 0; int CurrentDIBY = 0; int EdgingSpace = 2; int MaxHeightInCurrentLine = 0; // устанавливаем размеры if (FT_Set_Char_Size( InternalFace, InternalFontSize <<6, InternalFontSize <<6, 96, 96 )) { fprintf(stderr, "Can't set char size %i.", InternalFontSize); return; } // первый проход, формируем одну большую текстуру const char *CharsList2 = CharsList; while (strlen(CharsList) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList = utf8_to_utf32(CharsList, &CurrentChar); // загрузка глифа нужного нам символа if (FT_Load_Char( InternalFace, CurrentChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT)) { fprintf(stderr, "Can't load Char: %u\n", CurrentChar); return; } // создаем структуру FontChar eFontChar* NewChar; NewChar = new eFontChar; NewChar->UTF32 = CurrentChar; NewChar->CharTexture = 0; NewChar->FontSize = InternalFontSize; NewChar->TexturePositionLeft = 0; NewChar->TexturePositionRight = 0; NewChar->TexturePositionTop = 0; NewChar->TexturePositionBottom = 0; NewChar->Width = InternalFace->glyph->bitmap.width; NewChar->Height = InternalFace->glyph->bitmap.rows; NewChar->Left = InternalFace->glyph->bitmap_left; NewChar->Top = InternalFace->glyph->bitmap_top; NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f; NewChar->Prev = 0; NewChar->Next = 0; // делаем установку параметров для вклеивания // если в текущую строку символов уже не можем вписывать - смещаемся на новую, ниже if (CurrentDIBX + NewChar->Width > FontTextureWidth) { CurrentDIBX = 0; CurrentDIBY += MaxHeightInCurrentLine + EdgingSpace; MaxHeightInCurrentLine = 0; } // если в текущую строку не влазит уже по высоте - значит это фейл... кричим чтоб дали больше текстуру if (CurrentDIBY + NewChar->Height > FontTextureHeight) { fprintf(stderr, "!!! Can't generate all font chars in one texture. Too many chars or too small texture size!\n"); delete NewChar; break; } // "вклеиваем" новый символ в массив BYTE ColorRGB[3]={255,255,255}; for (int j=0; j<NewChar->Height; j++) for (int i=0; i<NewChar->Width; i++) { memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4, ColorRGB, 3); memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4 + 3, InternalFace->glyph->bitmap.buffer+j*NewChar->Width+i, 1); } // устанавливаем параметры текстуры для прорисовки нашему символу NewChar->TexturePositionLeft = CurrentDIBX; NewChar->TexturePositionRight = CurrentDIBX + NewChar->Width; NewChar->TexturePositionTop = CurrentDIBY; NewChar->TexturePositionBottom = CurrentDIBY + NewChar->Height; // выбираем наибольшую высоту символов if (MaxHeightInCurrentLine < NewChar->Height) MaxHeightInCurrentLine = NewChar->Height; // смещаем указатель CurrentDIBX += NewChar->Width + EdgingSpace; // подключаем к менеджеру vw_AttachFontChar(NewChar); } ///////////////////////////////// /* // выводим в tga файл сгенерированный DIB, если нужно проверить SDL_RWops *TgaFile = SDL_RWFromFile("fontgenerationtest.tga", "wb"); if (TgaFile == NULL) { fprintf(stderr, "Can't open VFS file for write.\n"); return; } unsigned char UselessChar = 0; // used for useless char. short int UselessInt = 0; // used for useless int. unsigned char ImageType = 2; // Type of image we are saving. unsigned char ImageBits = 32; // Bit depth. short int ImageWidth = (short int)FontTextureWidth; short int ImageHeight = (short int)FontTextureHeight; // пишем неиспользуемые данные SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); // тип картинки SDL_RWwrite(TgaFile, &ImageType, sizeof(unsigned char), 1); // пишем неиспользуемые данные SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); SDL_RWwrite(TgaFile, &UselessInt, sizeof(short int), 1); // записываем параметры картинки SDL_RWwrite(TgaFile, &ImageWidth, sizeof(short int), 1); SDL_RWwrite(TgaFile, &ImageHeight, sizeof(short int), 1); SDL_RWwrite(TgaFile, &ImageBits, sizeof(unsigned char), 1); // пишем неиспользуемые данные SDL_RWwrite(TgaFile, &UselessChar, sizeof(unsigned char), 1); // пишем данные диб массива SDL_RWwrite(TgaFile, DIB, FontTextureWidth*FontTextureHeight*4, 1); // закрываем файл SDL_RWclose(TgaFile); */ ///////////////////////////////// // создаем текстуру vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false); eTexture* FontTexture = vw_CreateTextureFromMemory(TextureName, DIB, FontTextureWidth, FontTextureHeight, 4, false); // освобождаем память delete [] DIB; if (FontTexture == 0) { fprintf(stderr, "Can't create font texture.\n"); return; } // второй проход, всем FontChars из списка, присваиваем сгенерированную текстуру while (strlen(CharsList2) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList2 = utf8_to_utf32(CharsList2, &CurrentChar); // ставим нашу общую текстуру eFontChar* TMPChar = vw_FindFontCharByUTF32(CurrentChar); if (TMPChar != 0) TMPChar->CharTexture = FontTexture; } printf("Font characters generation end.\n\n"); }
//----------------------------------------------------------------------------- // делаем генерацию нужных символов по списку генерируя одну текстуру //----------------------------------------------------------------------------- void vw_GenerateFontChars(int FontTextureWidth, int FontTextureHeight, const char * CharsList) { printf("Font characters generation start.\n"); // будем использовать последовательность как имя текстуры const char *TextureName = CharsList; // временный массив BYTE * DIB; DIB = new BYTE[FontTextureWidth*FontTextureHeight*4]; // всегда делаем rgba // устанавливаем 0 везде, чтобы потом не краcить rgb, а только формировать альфу memset(DIB, 0, FontTextureWidth*FontTextureHeight*4); // данные для работы с вклеиванием в текстуру int CurrentDIBX = 0; int CurrentDIBY = 0; int EdgingSpace = 2; int MaxHeightInCurrentLine = 0; // первый проход, формируем одну большую текстуру const char *CharsList2 = CharsList; while (strlen(CharsList) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList = utf8_to_utf32(CharsList, &CurrentChar); // загрузка глифа нужного нам символа if (FT_Load_Char( InternalFace, CurrentChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT)) { fprintf(stderr, "Can't load Char: %u\n", CurrentChar); return; } // создаем структуру FontChar eFontChar* NewChar; NewChar = new eFontChar; NewChar->UTF32 = CurrentChar; NewChar->CharTexture = 0; NewChar->TexturePositionLeft = 0; NewChar->TexturePositionRight = 0; NewChar->TexturePositionTop = 0; NewChar->TexturePositionBottom = 0; NewChar->Width = InternalFace->glyph->bitmap.width; NewChar->Height = InternalFace->glyph->bitmap.rows; NewChar->Left = InternalFace->glyph->bitmap_left; NewChar->Top = InternalFace->glyph->bitmap_top; NewChar->AdvanceX = InternalFace->glyph->advance.x / 64.0f; NewChar->Prev = 0; NewChar->Next = 0; // делаем установку параметров для вклеивания // если в текущую строку символов уже не можем вписывать - смещаемся на новую, ниже if (CurrentDIBX + NewChar->Width > FontTextureWidth) { CurrentDIBX = 0; CurrentDIBY += MaxHeightInCurrentLine + EdgingSpace; MaxHeightInCurrentLine = 0; } // если в текущую строку не влазит уже по высоте - значит это фейл... кричим чтоб дали больше текстуру if (CurrentDIBY + NewChar->Height > FontTextureHeight) { fprintf(stderr, "!!! Can't generate all font chars in one texture. Too many chars or too small texture size!\n"); delete NewChar; break; } // "вклеиваем" новый символ в массив BYTE ColorRGB[3]={255,255,255}; for (int j=0; j<NewChar->Height; j++) for (int i=0; i<NewChar->Width; i++) { memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4, ColorRGB, 3); memcpy(DIB + (FontTextureHeight-CurrentDIBY-j-1)*FontTextureWidth*4 + (CurrentDIBX+i)*4 + 3, InternalFace->glyph->bitmap.buffer+j*NewChar->Width+i, 1); } // устанавливаем параметры текстуры для прорисовки нашему символу NewChar->TexturePositionLeft = CurrentDIBX; NewChar->TexturePositionRight = CurrentDIBX + NewChar->Width; NewChar->TexturePositionTop = CurrentDIBY; NewChar->TexturePositionBottom = CurrentDIBY + NewChar->Height; // выбираем наибольшую высоту символов if (MaxHeightInCurrentLine < NewChar->Height) MaxHeightInCurrentLine = NewChar->Height; // смещаем указатель CurrentDIBX += NewChar->Width + EdgingSpace; // подключаем к менеджеру vw_AttachFontChar(NewChar); } ///////////////////////////////// /* // выводим в bmp файл сгенерированный DIB, если нужно проверить SDL_Surface *temp; temp = SDL_CreateRGBSurface(SDL_SWSURFACE, FontTextureWidth, FontTextureHeight, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0 #else 0x00FF0000, 0x0000FF00, 0x000000FF, 0 #endif ); memcpy(temp->pixels, DIB, FontTextureWidth*FontTextureHeight*4); SDL_SaveBMP(temp, "fontgenerationtest.bmp"); SDL_FreeSurface(temp); */ ///////////////////////////////// // создаем текстуру vw_SetTextureProp(RI_MAGFILTER_LINEAR | RI_MINFILTER_LINEAR | RI_MIPFILTER_NONE, RI_CLAMP_TO_EDGE, true, TX_ALPHA_GREYSC, false); eTexture* FontTexture = vw_CreateTextureFromMemory(TextureName, DIB, FontTextureWidth, FontTextureHeight, 4, false); // освобождаем память delete [] DIB; if (FontTexture == 0) { fprintf(stderr, "Can't create font texture.\n"); return; } // второй проход, всем FontChars из списка, присваиваем сгенерированную текстуру while (strlen(CharsList2) > 0) { unsigned CurrentChar; // преобразуем в утф32 и "сдвигаемся" на следующий символ в строке CharsList2 = utf8_to_utf32(CharsList2, &CurrentChar); // ставим нашу общую текстуру eFontChar* TMPChar = vw_FindFontCharByUTF32(CurrentChar); if (TMPChar != 0) TMPChar->CharTexture = FontTexture; } printf("Font characters generation end.\n\n"); }