Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Failing to load font [basic program]

This thread is locked; no one can reply to it. rss feed Print
Failing to load font [basic program]
tikonwc3
Member #14,641
October 2012

Hey guys I've just been playing around with allegro 5, and playing with examples from codingmadeeasy, this is an example from him, and It works fine when he compiles it. He is however using vs and i'm using codeblocks. The code is

[code]// C++ ALLEGRO 5 MADE EASY TUTORIAL 5 - FONT & TEXT
// CODINGMADEEASY

#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_font.h>

#define ScreenWidth 800
#define ScreenHeight 600

int main()
{
ALLEGRO_DISPLAY *display;

if(!al_init())
{
al_show_native_message_box(NULL, NULL, "Error", "Could not initialize Allegro 5", NULL, ALLEGRO_MESSAGEBOX_ERROR);
return -1;
}
display = al_create_display(ScreenWidth, ScreenHeight);

if(!display)
{
al_show_native_message_box(NULL, NULL, "Error", "Could not create Allegro 5 display", NULL, ALLEGRO_MESSAGEBOX_ERROR);
return -1;
}

// You generally want to do this after you check to see if the display was created. If the display wasn't created then there's
// no point in calling this function
al_set_new_display_flags(ALLEGRO_NOFRAME);
al_set_window_position(display, 200, 100);
al_set_window_title(display, "CodingMadeEasy");

al_init_font_addon();
al_init_ttf_addon();

ALLEGRO_FONT *font = al_load_font("font.ttf", 36, NULL);
al_draw_text(font, al_map_rgb(44, 117, 255), ScreenWidth / 2, ScreenHeight / 2, ALLEGRO_ALIGN_CENTRE, "www.codingmadeeasy.ca");

al_flip_display();
al_rest(10.0);

al_destroy_font(font);
al_destroy_display(display);

return 0;
}
[/code]

The error given is ..

Assertion failed C:\ ...
File:allegro-5.0.x/addons/font/text.c
line 73

expression : Font

So my original though was maybe I needed to use my own font, So I downloaded it from urban fonts, placed it in project folder and set it up to use it, the font name is molten and was set accordingly and doesn't give the error when it pops up...but after a few seconds it crashes..

and advice/help appreciated.
thanks for reading.

taron 
Member #10,584
January 2009
avatar

That program will shut down after it has been open for 10 seconds.

Also this site uses SGML/HTML/XML style tags. Like: <code>

Cassio Renan
Member #14,189
April 2012
avatar

Use <code>, not [code] to show code in your post.

If I'm not wrong, al_load_font() (Actually, al_load_ttf_font(), since you're using a truetype font) returns NULL on error.
Check if variable font isn't null after loading. If it is, a problem happened while loading it. You can try changing the folder it is placed. Also, try checking if the font's name(and extension) is exactly the same of what you're trying to load.

tikonwc3
Member #14,641
October 2012

Thanks for the quick response, I double checked to make sure I had the extension and name correct, both are :)

As far as checking the value of font, I tried using cout to print its value to the console, however nothing comes out

Cassio Renan
Member #14,189
April 2012
avatar

for that you can just test it against NULL.

ALLEGRO_FONT *font = al_load_font("font.ttf", 36, NULL);
if(font == NULL) return ERR_CANT_LOAD_FONT // fictitious error constant. You might want to return 1 or any other non-zero value

alternatively,

ALLEGRO_FONT *font = al_load_font("font.ttf", 36, NULL);
if(!font) return ERR_CANT_LOAD_FONT // fictitious error constant. You might want to return 1 or any other non-zero value

tikonwc3 said:

doesn't give the error when it pops up

You mean the display or the text? I mean, is the text showing, or there's only a black window?

tikonwc3
Member #14,641
October 2012

Sorry, to clarify what I meant by nothing pops up, is that there is no text.

The window is white though, and I have it set so a console will appear for purposes of debugging, but more specifically I meant that it won't print anything to console, its entirely blank when the program crashes.

Thanks!

Arthur Kalliokoski
Second in Command
February 2005
avatar

If you have a console, you should be able to see

#include <stdio.h>  //for fprintf()
#include <stdlib.h> //for exit()
if(font == NULL)
{
   fprintf(stderr,"Can't load font\n");
   exit(1);
}

That said, if it can't load the font it might be the compiler changing the directory, you can get around this with al_get_standard_path(ALLEGRO_EXENAME_PATH);

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

tikonwc3
Member #14,641
October 2012

Thank you for the reply.

I added in this.

#SelectExpand
1// C++ ALLEGRO 5 MADE EASY TUTORIAL 5 - FONT & TEXT 2// CODINGMADEEASY 3#include <stdio.h> 4#include <iostream> 5#include <allegro5/allegro.h> 6#include <allegro5/allegro_native_dialog.h> 7#include <allegro5/allegro_ttf.h> 8#include <allegro5/allegro_font.h> 9 10#define ScreenWidth 800 11#define ScreenHeight 600 12 13int main() 14{ 15 ALLEGRO_DISPLAY *display; 16 17 if(!al_init()) 18 { 19 al_show_native_message_box(NULL, NULL, "Error", "Could not initialize Allegro 5", NULL, ALLEGRO_MESSAGEBOX_ERROR); 20 return -1; 21 } 22 display = al_create_display(ScreenWidth, ScreenHeight); 23 24 if(!display) 25 { 26 al_show_native_message_box(NULL, NULL, "Error", "Could not create Allegro 5 display", NULL, ALLEGRO_MESSAGEBOX_ERROR); 27 return -1; 28 } 29 30 // You generally want to do this after you check to see if the display was created. If the display wasn't created then there's 31 // no point in calling this function 32 al_set_new_display_flags(ALLEGRO_NOFRAME); 33 al_set_window_position(display, 200, 100); 34 al_set_window_title(display, "CodingMadeEasy"); 35 36 al_init_font_addon(); 37 al_init_ttf_addon(); 38 39 40 al_get_standard_path(ALLEGRO_EXENAME_PATH); 41 ALLEGRO_FONT *font = al_load_font("molten.ttf", 36, NULL); 42 al_draw_text(font, al_map_rgb(44, 117, 255), ScreenWidth / 2, ScreenHeight / 2, ALLEGRO_ALIGN_CENTRE, "www.codingmadeeasy.ca"); 43 44 al_flip_display(); 45 al_rest(10.0); 46 47 al_destroy_font(font); 48 if(font == NULL) 49{ 50 fprintf(stderr,"Can't load font\n"); 51 exit(1); 52} 53 al_destroy_display(display); 54 55 return 0; 56}

But no change is seen. It still doesn't print to console and crashes

Thanks again for reply

Kris Asick
Member #1,424
July 2001

Two things:

1. You need to check the return result of al_load_font() IMMEDIATELY after calling it. Currently, you don't check the return until after your program has run its course.

2. al_set_new_display_flags() has to be called before calling al_create_display(). This is why the command is called "new display flags", since it only affects new displays created afterwards.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

tikonwc3
Member #14,641
October 2012

I can't believe I didn't catch that I even put it after it was destroyed, that was stupid of me. I have rectified this so my code is now

#SelectExpand
1// C++ ALLEGRO 5 MADE EASY TUTORIAL 5 - FONT & TEXT 2// CODINGMADEEASY 3#include <stdio.h> 4#include <iostream> 5#include <allegro5/allegro.h> 6#include <allegro5/allegro_native_dialog.h> 7#include <allegro5/allegro_ttf.h> 8#include <allegro5/allegro_font.h> 9 10#define ScreenWidth 800 11#define ScreenHeight 600 12 13int main() 14{ 15 ALLEGRO_DISPLAY *display; 16 17 if(!al_init()) 18 { 19 al_show_native_message_box(NULL, NULL, "Error", "Could not initialize Allegro 5", NULL, ALLEGRO_MESSAGEBOX_ERROR); 20 return -1; 21 } 22 al_set_new_display_flags(ALLEGRO_NOFRAME); 23 display = al_create_display(ScreenWidth, ScreenHeight); 24 25 if(!display) 26 { 27 al_show_native_message_box(NULL, NULL, "Error", "Could not create Allegro 5 display", NULL, ALLEGRO_MESSAGEBOX_ERROR); 28 return -1; 29 } 30 31 // You generally want to do this after you check to see if the display was created. If the display wasn't created then there's 32 // no point in calling this function 33 al_set_new_display_flags(ALLEGRO_NOFRAME); 34 al_set_window_position(display, 200, 100); 35 al_set_window_title(display, "Font Test"); 36 37 al_init_font_addon(); 38 al_init_ttf_addon(); 39 40 41 al_get_standard_path(ALLEGRO_EXENAME_PATH); 42 43 ALLEGRO_FONT *font = al_load_font("drakon.ttf", 36, NULL); 44 if(font == NULL) 45 { 46 fprintf(stderr,"Can't load font\n"); 47 exit(1); 48 } 49 al_draw_text(font, al_map_rgb(44, 117, 255), ScreenWidth / 2, ScreenHeight / 2, ALLEGRO_ALIGN_CENTRE, "www.codingmadeeasy.ca"); 50 51 al_flip_display(); 52 al_rest(10.0); 53 54 al_destroy_font(font); 55 al_destroy_display(display); 56 57 return 0; 58}

Trent Gamblin
Member #261
April 2000
avatar

And what happened?

You won't see fprintf on Windows unless you build a special way. Try using al_show_native_message_box instead.

tikonwc3
Member #14,641
October 2012

I used a messagebox instead of printf or cout, however it doesn't load. It comes right after font is declared and set.

Thanks!

weapon_S
Member #7,859
October 2006
avatar

Kris Asick
Member #1,424
July 2001

Something else I noticed: al_get_standard_path() doesn't actually change or set path information. It creates and returns a pointer to an ALLEGRO_PATH object. This means you will have a memory leak if you don't put the results of the call into an ALLEGRO_PATH pointer, plus if you actually want to use an ALLEGRO_PATH object to properly obtain a file location, you need to use combinations of al_set_path_filename() and al_path_cstr(). Here's the function I wrote to simplify loading textures from a textures folder off of my main game folder:

ALLEGRO_BITMAP *VZ_LoadBitmap (const char *filepath, const char *filename, int bitmap_flags) 
{
  // This is merely a function to simplify bitmap loading. Return values are identical to al_load_bitmap()
  ALLEGRO_BITMAP *tempbmp;
  al_destroy_path(temppath); temppath = al_clone_path(gamepath); al_append_path_component(temppath,filepath); al_set_path_filename(temppath,filename);
  al_set_new_bitmap_flags(bitmap_flags);
  tempbmp = al_load_bitmap(al_path_cstr(temppath,ALLEGRO_NATIVE_PATH_SEP));
  return tempbmp;
}

Note that "temppath" and "gamepath" are defined as global pointers to ALLEGRO_PATH objects and that gamepath has been set at the start of the program using al_get_standard_path(). Also, the first al_destroy_path(temppath) call only works because I specifically set all pointers I use to NULL at the start of my programs, otherwise this would crash everything.

It also may look like my call to al_path_cstr() is a memory leak, but the pointer is actually tracked by the ALLEGRO_PATH object so I don't have to worry about it. ;)

--- Kris Asick (Gemini)
--- http://www.pixelships.com

tikonwc3
Member #14,641
October 2012

Thank you for the detailed post! Could I ask for a little more detail on how to use it though? I'm in a hurry so forgive my quick post, but you said linking to an allegro program file, which I don't understand, I installed it by drag and drop the bin include and lib folders.

I'm sorry for the hasty reply but College + work = pain in the ass >_<

Thanks again

Kris Asick
Member #1,424
July 2001

Uhh... slow down and actually have time to read stuff before you respond again. I never said anything like that... *reads up* ...doesn't look like anyone else did either. :P

--- Kris Asick (Gemini)
--- http://www.pixelships.com

tikonwc3
Member #14,641
October 2012

Sorry about the hasty reply. But thanks a lot for your excerpt.

I'm pretty new to allegro and I won't lie that looks pretty scary..But id be a horrible programmer if I let everything scare me away :P

So from what youve told me I'm wanting to do something like this..

string *path = al_path_cstr("c:\...";
//then use 
al_get_standard_path(*path);

Thanks again for reading

Kris Asick
Member #1,424
July 2001

Uh... No.

The following is essentially what you need to do to work with filenames and paths with Allegro's built-in functions. Use the Allegro Manual to get information on the usage of these functions:

1. Create a pointer to an ALLEGRO_PATH object.
2. Use al_get_standard_path() to assign a path to your ALLEGRO_PATH object.
3. Use al_set_path_filename() to set the name of the file you want to load in your ALLEGRO_PATH object.
4. When you're ready to load your file, use al_path_cstr() to acquire a string pointer for use directly in a loading command, like al_load_font(). The string returned is stored and tracked by the ALLEGRO_PATH object that generated it, so you can treat the result like a constant instead of as an object that needs to be destroyed.
5. When you're done with your ALLEGRO_PATH object, call al_destroy_path() on it.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

tikonwc3
Member #14,641
October 2012

I'm having trouble with step 3 of that. so far I have this
<code>
ALLEGRO_PATH *myPath = al_get_standard_path(ALLEGRO_EXENAME_PATH);
al_set_path_filename(*myPath, const char *filename = "drakon.ttf");
</code.>

so in the manual it gives this

void al_set_path_filename(ALLEGRO_PATH *path, const char *filename)

I'm at a loss here, I've already created my allegro path object, and declared my al_set_path_filename, so why created a function to set them again?

Thanks

Thomas Fjellstrom
Member #476
June 2000
avatar

I think you might need to study up on C/C++ a bit more. Your code there shows a lack of basic C/C++ knowledge.

--
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

Kris Asick
Member #1,424
July 2001

More-so a lack of pointer knowledge. *'s indicate that you either want to create a pointer to a variable, that you want to grab the information from a pointed variable, or that a function wants a pointer as one of its arguements.

Like:

int *PointerToInt;
ThisFunctionWantsAPointer(PointerToInt);
ThisFunctionWantsAnInt(*PointerToInt);

Or, you can grab the pointer of a non-pointer variable using an ampersand, like so:

int MyInt;
ThisFunctionWantsAnInt(MyInt);
ThisFunctionWantsAPointer(&MyInt);

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Raidho36
Member #14,628
October 2012
avatar

I'm fine with pointers, but this explanation really confused me.

To make it simple, I'll just state it as is:
Pointer is an integer that contains an absolute address to some place in a memory, no more than that. Type of a pointer only helps to know how much data is supposed to be there where pointer points to.

#SelectExpand
1int i; 2int * i_ptr; 3int * a; 4 5i = 10; 6/* this puts address of i to a_ptr */ 7i_ptr = &i; 8/* this prints whatever i_ptr actually contains itself */ 9printf ( "%p ", i_ptr ); 10/* and this prints dereferenced i_ptr, i.e. assuming i_ptr points to an int */ 11printf ( "%d\n", *i_ptr ); 12/* if you change the value the pointer points to, pointer itself won't change, 13 * but the value pointed by it - will (duh) */ 14i = 15; 15printf ( "%p %d\n", i_ptr, *i_ptr ); 16/* you can also modify a value by dereferencing a pointer */ 17*i_ptr = 30; 18printf ( "%p %d\n", i_ptr, *i_ptr ); 19/* you can dereference a value pointed by pointer as a different type, 20 * but it will just give you garbage if types are incompatible */ 21printf ( "%p %c\n", (char*)i_ptr, *(char*)i_ptr ); 22/* the most common use of pointers though is remembering where you allocated 23 * your memory */ 24a = malloc ( sizeof ( int ) * 32 ); 25/* With memory allocated like that, you can do pointer math. The pointer acts 26 * not like an integral value, but as a index number for memory cells exactly as 27 * large to contain a single int in them. The following sets zeroth cell to 0, 28 * first cell to 10 and second cell to 20. */ 29*(a + 0) = 0; 30*(a + 1) = 10; 31*(a + 2) = 20; 32/* And that would output contents of first four cells. Note that third cell 33 * contains garbage - this is normal. Memory allocation does not reset anything 34 * that was in the allocated memory block, so if you require initialzied memory, 35 * you'll have to either do it yourself or call calloc. */ 36printf ( "%p %d %d %d %d\n", a, *(a + 0), *(a + 1), *(a + 2), *(a + 3) ); 37/* This moves a pointer once cell forward. Note that if you want to call free, 38 * you will need to provide precisely the value returned by previous malloc. */ 39a += 1; 40printf ( "%p %d %d\n", a, *(a + 0), *(a + 1 ) ); 41/* there also another, more conventional notation to dereference allocated 42 * memory cells */ 43a [ 2 ] = 30; 44a [ 3 ] = 40; 45printf ( "%p %d %d\n", a, a [ 2 ], a [ 3 ] );

Thomas Fjellstrom
Member #476
June 2000
avatar

More-so a lack of pointer knowledge.

You might want to check his code again:

ALLEGRO_PATH *myPath = al_get_standard_path(ALLEGRO_EXENAME_PATH);
al_set_path_filename(*myPath, const char *filename = "drakon.ttf");

Particularly the second argument to al_set_path_filename.

--
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

Go to: