2017-08-16 59 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