2017-08-16 18 views
0

剛剛創建了一個函數來緩存我在SDL2中構建的小遊戲引擎中的任何加載的字體,以下函數完美地工作,並且渲染文本比每次創建新的SDL_Surface快12倍我需要文字。然而,正如你所看到的,它只緩存ANSI字符,這是好的英語,但如果我曾經想翻譯我的遊戲(德語變音,或西里爾字形不可在ANSI)SDL2中的UTF文本

void cacheFonts(){ 
    for(unsigned int i = 0; i < GlobalFontAssets.size; i++){ 
     SDL_Colour color_font = {255, 255, 255, 255}; 
     std::vector<SDL_Texture*> tempVector; 
     for(int j = 32; j < 128; j++){ 
      char temp[2]; 
      temp[0] = j; 
      temp[1] = 0; 
      SDL_Surface* glyph = TTF_RenderUTF8_Blended(GlobalFontAssets.fonts[i], temp, color_font); 
      SDL_Texture* texture = 
      SDL_CreateTextureFromSurface(renderer, glyph); 
      tempVector.push_back(texture); 
      SDL_FreeSurface(glyph); 
     } 
     GlobalFontAssets.cache.push_back(tempVector); 
    } 
    printf("Global Fonts Cached!\n"); 
} 

我使用wchar_t,從0到256^2循環都試過了,但我不能得到任何字符使用printfwprintfcoutwcout打印偶數,但是,如果我做的:

std::string str = "Привет, öäü" 
printf("%s\n", str.c_str()); 

然後打印字符串在終端上就好了。我應該提到,我使用的是Ubuntu 16.04,因此僅Windows的解決方案對我無效,理想情況下我希望以便攜方式進行操作。對於那些不熟悉SDL的人來說,我所需要的只是一種獲取C字符串中每個UTF8字符的方法。我希望這是可能的。

+3

嗯,C-ish C++代碼。建議只有1個語言標記來改善帖子。 – chux

+0

與256個擴展ASCII字符相比,有*百萬*的Unicode字形。你不能盲目地使用相同的方法。除此之外,在Unicode中有「組合字符」,它們不能與修飾字符分開渲染,你必須處理字形單位而不是字符單位。 –

+0

@BenVoigt你的意思是Latin-1而不是ASCII? – Deduplicator

回答

1

解決這個問題的只有這個部分:

所有我需要的是一種方式來獲得在C字符串

Wikipedia has a nice table每UTF8字符,顯示出不同的編碼規則,碼點的範圍每個覆蓋,以及相應的UTF-8長度和數據字節。

覆蓋the first 2000-odd characters,只是生成所有一個和兩個字節模式:

char s[3] = { 0 }; 
for(s[0] = 0x00; s[0] < 0x80u; ++s[0]) { // can start at 0x20 to skip control characters 
    // one byte encodings 
} 
for(s[0] = 0xC0u; s[0] < 0xE0u; ++s[0]) { 
    for(s[1] = 0x80u; s[1] < 0xC0u; ++s[1]) { 
     // two byte encodings 
    } 
} 

這並非巧合的是,值0x80u0xC0u不止一次出現在循環條件 - 事實上,有在前導字節和後續字節之間沒有重疊是UTF-8的自同步屬性。

我想你是依靠以下事實(維基百科的引用):

前128個字符(US-ASCII)需要一個字節。接下來的1,920個字符需要兩個字節進行編碼,其中涵蓋了幾乎所有拉丁字母字母的其餘部分,還包括希臘語,西里爾語,科普特語,亞美尼亞語,希伯來語,阿拉伯語,敘利亞語,塔那那語和N'Ko字母以及組合變音詞分數。

由於此範圍包含組合標記,因此您將會有不少單個條目無法單獨渲染。無論是跳過它們還是僅僅處理由文本佈局引擎引起的混淆都取決於您。

+0

這確實做了我所問的,謝謝。然而,我已決定改變我的方法。我現在只用這種方式緩存ASCII字符,因爲它根本不需要太多vram,並且繪製速度非常快。對於非ASCII文本,我使用'std :: list'和'std :: unordered_map'創建了一個LRU緩存,它包含最後100個字符串的繪製。當文本不發生非常快的變化時,就像前一種方法一樣快,當然,一旦創建了緩存。我現在只檢查一個字符串是否使用任何非標準字符並使用適當的函數。我認爲我可以緩存所有的UTF8真的很瘋狂。 – Max