Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] TTF Fonts not caching correctly?

This thread is locked; no one can reply to it. rss feed Print
 1   2 
[A5] TTF Fonts not caching correctly?
jmasterx
Member #11,410
October 2009

I'm using Allegro 5.0.5

In the game I'm making, the game's text dynamically resizes and therefore I load and use a lot of fonts.

Each Gui component, when receiving a resize event accesses the font manager and sets its font to the appropriate font.

I load fonts in the constructor of the core class, after Allegro has been initialized and after a display has been created.

#SelectExpand
1 Core::Core(int argc, char *argv[]) 2 :display(NULL), 3 m_fontManager(NULL) 4 { 5 //initialize Allegro 5 6 _initAllegro(); 7 8 //initialize Agui 9 _initAgui(); 10 11 //create the display 12 Vec2 optimalSize = Display::getOptimalResoluton(); 13 display = new Display(optimalSize.getX(),optimalSize.getY()); 14 appIcon = new Sprite("res/appico.png"); 15 display->setIcon(appIcon); 16 17 //init font manager 18 m_fontManager = new GuiFontManager("res/font.ttf",8,32,17); 19 agui::Widget::setGlobalFont(m_fontManager->getDefaultFont()); 20 21 //create the scene manager 22 sceneManager = new SceneManager(settings, m_dynamicUIManager); 23 display->setSceneMessenger(sceneManager); 24 25 } 26... 27 GuiFontManager::GuiFontManager( 28 const std::string& fontPath, int beginRange, int endRange, int defaultSize ) 29 : m_beginRange(beginRange), m_endRange(endRange), m_defaultSize(defaultSize) 30 { 31 for(int i = beginRange; i <= endRange; ++i) 32 { 33 m_fonts.push_back(agui::Font::load(fontPath,i)); 34 } 35 }

My issue is when I get into a scene and start using a bunch of these fonts. Sometimes only part of a word is rendered, and on occasion, a glyph is totally the wrong one. I also tried, after loading a font to render the alphabet and this actually helped, but there were still certain circumstances when the word 'Across' rendered as 'Acro' or 'o'. I've looked through my code for hours trying to find something wrong with it but I cannot seem to find anything wrong.

Is there some sort of precaution to take when loading and using around 40 TTF fonts?

Thanks

MiquelFire
Member #3,110
January 2003
avatar

Sounds like an issue I had with my last SpeedHack game, only I loaded only two. In my case, only some computers failed to load the fonts correctly.

---
Febreze (and other air fresheners actually) is just below perfumes/colognes, and that's just below dead skunks in terms of smells that offend my nose.
MiquelFire.red | +Me
Windows 8 is a toned, stylish, polished professional athlete. But it’s wearing clown makeup, and that creates a serious image problem. ~PCWorld Article

jmasterx
Member #11,410
October 2009

On my PC, the same exe and conditions cause different letters to show and different letters not to... I do not know what to do. It is very important for me to be able to have this feature.

Edit:

I can confirm that this only happens with Direct3D, not OpenGL.

Peter Wang
Member #23
April 2000

Best provide a test case.

Trent Gamblin
Member #261
April 2000
avatar

I think I had a similar issue with the D3D driver at one point. I fixed it by making sure bitmaps were a minimum size, I think 16x16. Not sure if it's related. I don't know for certain but I assumed that fix was either done before 5.0 was released or ported back.

jmasterx
Member #11,410
October 2009

Here is an example that produces the problem.

It seems to happen when calling al_get_text_width and loading many fonts.

#SelectExpand
1#include <stdio.h> 2#include <allegro5/allegro.h> 3#include <allegro5/allegro5.h> 4#include <allegro5/allegro_primitives.h> 5#include <allegro5/allegro_font.h> 6#include <allegro5/allegro_ttf.h> 7#include "stdlib.h" 8#include <vector> 9struct Example 10{ 11 double fps; 12 ALLEGRO_CONFIG *config; 13} ex; 14//Globals are bad but it is an example 15std::vector<ALLEGRO_FONT*> m_fonts; 16 17static const char *get_string(const char *key) 18{ 19 const char *v = al_get_config_value(ex.config, "", key); 20 return (v) ? v : key; 21} 22 23static void render(void) 24{ 25 al_clear_to_color(al_map_rgb(0,0,0)); 26 27 int fontSz = al_get_display_height(al_get_current_display()) * 0.03f; 28 if(fontSz >= m_fonts.size()) 29 { 30 fontSz = m_fonts.size() - 1; 31 } 32 33 al_draw_text((m_fonts[fontSz]),al_map_rgb(255,255,255),0,0,0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 34 35 al_get_text_width(m_fonts[6],"ALLEGRO"); 36} 37 38int main(int argc, const char *argv[]) 39{ 40 const char *font_file = "data/DejaVuSans.ttf"; 41 ALLEGRO_DISPLAY *display; 42 ALLEGRO_TIMER *timer; 43 ALLEGRO_EVENT_QUEUE *queue; 44 int redraw = 0; 45 double t = 0; 46 47 if(!al_init()) 48 { 49 return 1; 50 } 51 52 53 if(!al_init_primitives_addon()) 54 { 55 return 1; 56 } 57 58 al_init_font_addon(); 59 60 if(!al_init_ttf_addon()) 61 { 62 return 1; 63 } 64 65 66 al_set_new_display_flags(ALLEGRO_RESIZABLE); 67 display = al_create_display(640, 480); 68 if (!display) { 69 return 1; 70 } 71 al_install_keyboard(); 72 73 //load the fonts 74 for(int i = 8; i < 32; ++i) 75 { 76 m_fonts.push_back(al_load_font(font_file,i,0)); 77 } 78 79 timer = al_create_timer(1.0 / 60); 80 81 queue = al_create_event_queue(); 82 al_register_event_source(queue, al_get_keyboard_event_source()); 83 al_register_event_source(queue, al_get_display_event_source(display)); 84 al_register_event_source(queue, al_get_timer_event_source(timer)); 85 86 al_start_timer(timer); 87 while (true) { 88 ALLEGRO_EVENT event; 89 al_wait_for_event(queue, &event); 90 if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 91 break; 92 if (event.type == ALLEGRO_EVENT_KEY_DOWN && 93 event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 94 break; 95 } 96 if (event.type == ALLEGRO_EVENT_TIMER) 97 redraw++; 98 99 if(event.type == ALLEGRO_EVENT_DISPLAY_RESIZE) 100 { 101 al_acknowledge_resize(display); 102 103 } 104 105 while (redraw > 0 && al_is_event_queue_empty(queue)) { 106 double dt; 107 redraw--; 108 109 dt = al_get_time(); 110 render(); 111 dt = al_get_time() - dt; 112 113 t = 0.99 * t + 0.01 * dt; 114 115 ex.fps = 1.0 / t; 116 al_flip_display(); 117 } 118 } 119 //free mem 120 121 return 0; 122} 123 124/* vim: set sts=4 sw=4 et: */

Just keep resizing the window until you see the image I've attached:
{"name":"605475","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/0\/6057c40463519de97417fc003c88ed78.png","w":742,"h":308,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/0\/6057c40463519de97417fc003c88ed78"}605475

It's quite tricky to reproduce. If I draw the alphabet with all the loaded fonts the issue does not occur.

Trent Gamblin
Member #261
April 2000
avatar

Something to do with display lost/found probably. When you resize a window D3D has to reinit all bitmaps from system memory, including fonts.

jmasterx
Member #11,410
October 2009

Do you think it can be fixed? I do not want to use GL on Windows because:

When it resizes it flickers. Theres no way to address this because I cant get a resize begin / end events and therefore cannot render black while resizing.

And it reduces a lot of compatibility. If a person does not have an OpenGL driver from NVidia or ATI Allegro does not work well.

Also, it seems like it does have to do with resizing. If I launch the Window at 320x240, it does not happen (but in my game it still does, just differently).

Trent Gamblin
Member #261
April 2000
avatar

I'm sure it can be fixed. Change the fonts to use memory bitmaps. See if that "fixes" it. I know it'll be slow but that'll narrow down the bug.

jmasterx
Member #11,410
October 2009

Yup
Adding:
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);

'fixes' the problem.

It also 'fixes' it for my game.

Trent Gamblin
Member #261
April 2000
avatar

Now try cycling through different sizes without resizing (using video bitmaps). Just have a font_index, increase it each render and wrap it around to zero. See if you have any problems.

jmasterx
Member #11,410
October 2009

Cycling does not have the issue. However, when cycling, I can resize and the issue does not happen.

Trent Gamblin
Member #261
April 2000
avatar

Yeah, it seems like a threading issue. WM_SIZE events come in on a separate thread than the user thread (the one you write your code on.) So a bitmap "backup" must be performed before the resize takes place, and _flip() should probably be blocked with a mutex until all of this is done.

Thomas Fjellstrom
Member #476
June 2000
avatar

If the bitmaps are invalidated, just send down the LOST_DISPLAY event and call it a day ;)

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Trent Gamblin
Member #261
April 2000
avatar

That's not required to be handled by Allegro user programs. They can handle it if they choose, and skip all of the automatic stuff in favor of perhaps a little more performance and flexibility. But I think it's too complicated and different from other platforms that it shouldn't be the only way.

jmasterx
Member #11,410
October 2009

Most games I see using D3D that resize do postpone display flipping until resizing is done. This causes the game to also look better when resizing. Instead of a fuzzy stretched version of your output you get the last frame and some black which to me looks more elegant anyways. It just seems to me like it is better not to render while resizing; On all platforms too.

Trent Gamblin
Member #261
April 2000
avatar

Can you build 5.1 svn and try that? It probably doesn't work, but you'll be ready to test some patches in case I feel like trying to fix this now :D.

jmasterx
Member #11,410
October 2009

Would you happen to have FreeType and some of Allegro's other deps (for MSVC 9)? Otherwise it might take a while. I can compile core Allegro without trouble, but the TTF and other addons need the deps.

Trent Gamblin
Member #261
April 2000
avatar

I don't have them, but they come with the A5 binaries on this page that Michal Cichon makes.

jmasterx
Member #11,410
October 2009

Wouldn't I still need the headers though? I added the .libs to my PATH environment variable and CMAKE still cannot find them.

MiquelFire
Member #3,110
January 2003
avatar

I was going to say use the libs from the binary package of 5.0.5, but I noticed you would need to deal with static compiling to do that...

[edit] Just noticed that the only header included is the Physfs one (assuming an example needs it)

---
Febreze (and other air fresheners actually) is just below perfumes/colognes, and that's just below dead skunks in terms of smells that offend my nose.
MiquelFire.red | +Me
Windows 8 is a toned, stylish, polished professional athlete. But it’s wearing clown makeup, and that creates a serious image problem. ~PCWorld Article

jmasterx
Member #11,410
October 2009

[edit] Just noticed that the only header included is the Physfs one (assuming an example needs it)

Exactly, that's my problem.

Peter Wang
Member #23
April 2000

I seem to have this file on my Windows system. FreeType comes with MSVC build stuff in builds/win32 so it should not be that hard to build yourself anyway.

http://libagar.org/FreeType235-win32-i386.zip

Edit: here is a copy of one of my deps directories (I have a few). I do not remember if it works, where all the files came from, how they were built, if anything is missing, or if it is virus infected (I don't use antivirus). Use at your own risk.

http://uploading.com/files/9b797f94/deps.zip/

jmasterx
Member #11,410
October 2009

Has there been any progress on the issue. I do not know if you saw the similar OpenGL issue here as well:
http://www.allegro.cc/forums/thread/609417

(Maybe this thread and the other should be moved to the Development section since I guess it is an allegro bug and not an issue with my code which had been my initial speculation)

Also, I compiled FreeType, but I'm not sure how to get CMAKE to know where it is.

Elias
Member #358
May 2000

Easiest way is to drop it (both the include and lib folder) into a folder called "deps" in the build folder.

--
"Either help out or stop whining" - Evert

 1   2 


Go to: