PDA

View Full Version : Loading TTF fonts from resources in 3.0



Nightwind0
11-01-2013, 05:14 PM
I'm not seeing a way to load TTF fonts from resources. Prior to 3.0, I had fonts in resources, but I'm not seeing a way to do that in 3.0. I tried putting the resource ID in the font description name, and then it attempted to load the TTF, but it couldn't find the file referenced in my "ttf" element.

What's the right way to load a ttf font from resources?

I need a solution for this asap, any help is greatly appreciated!

EDIT: After reading the code, it looks to me like Font_Impl::load_font doesn't try to load from resources at all.... In previous versions, I was able to pull an IODevice from the resources and construct a CL_Font_Freetype and pass that IODevice in to the constructor, which let me load TTF fonts from resources... I need to be able to do this in 3.0 as well. Help!

rombust
11-02-2013, 11:39 PM
Did you look at http://clanlib.org/documentation/3.0/FontResource.html "Using the <ttf> element"

For example (from looking at the docs)


<font name="mysuperfont">
<ttf file="resources/mysuperfont.ttf"/>
</font>

And use:




static Resource<Font> clan::Font::resource (Canvas & canvas, const FontDescription & desc, const ResourceManager & resources )

Retrieves a Font resource from the resource manager.

eg
clan::FontDescription desc;
desc.set_typeface_name("mysuperfont");
desc.set_height(24);
clan::Font mysuperfont = clan::Font::resource(canvas, desc, resources);

Nightwind0
11-03-2013, 12:33 AM
Did you look at http://clanlib.org/documentation/3.0/FontResource.html "Using the <ttf> element"

For example (from looking at the docs)


<font name="mysuperfont">
<ttf file="resources/mysuperfont.ttf"/>
</font>

And use:




static Resource<Font> clan::Font::resource (Canvas & canvas, const FontDescription & desc, const ResourceManager & resources )

Retrieves a Font resource from the resource manager.

eg
clan::FontDescription desc;
desc.set_typeface_name("mysuperfont");
desc.set_height(24);
clan::Font mysuperfont = clan::Font::resource(canvas, desc, resources);

Yeah, this is what I tried. It doesnt find the file and throws an exception.


EDIT: I managed to get it to work but I had to provide the full path to the ttf file. In other words, I can't simply refer to it inside my resources the way I can other resources. Is this a bug, or a restriction of version 3.0?

rombust
11-03-2013, 08:04 AM
I had a quick look at the source, it looks like a bug:

In Sources/Display/font.cpp

Font Font_Impl::load(Canvas &canvas, const FontDescription &reference_desc, const std::string &id, const XMLResourceDocument &doc, Callback_2<Resource<Sprite>, Canvas &, const std::string &> cb_get_sprite)

Change...


if (ttf_element.has_attribute("file"))
filename = ttf_element.get_attribute("file"); desc.set_typeface_name(ttf_element.get_attribute("file"));


To...



if (ttf_element.has_attribute("file"))
{
filename = PathHelp::combine(resource.get_base_path(), ttf_element.get_attribute("file"));
desc.set_typeface_name(ttf_element.get_attribute("file"));
}

If that works, we will apply the patch.

Nightwind0
11-03-2013, 04:37 PM
I had a quick look at the source, it looks like a bug:

In Sources/Display/font.cpp

Font Font_Impl::load(Canvas &canvas, const FontDescription &reference_desc, const std::string &id, const XMLResourceDocument &doc, Callback_2<Resource<Sprite>, Canvas &, const std::string &> cb_get_sprite)

Change...


if (ttf_element.has_attribute("file"))
filename = ttf_element.get_attribute("file"); desc.set_typeface_name(ttf_element.get_attribute("file"));


To...



if (ttf_element.has_attribute("file"))
{
filename = PathHelp::combine(resource.get_base_path(), ttf_element.get_attribute("file"));
desc.set_typeface_name(ttf_element.get_attribute("file"));
}

If that works, we will apply the patch.

Yay, that works, thank you!! By the way, I also had to include "path_help.h" in font.cpp when I made that change.

Nightwind0
11-03-2013, 05:27 PM
Thanks again for the patch! It's working for me in my Linux build (I haven't tried windows yet)


By the way, I was looking at the Font Engine for win32 code, like this:

AddFontResourceEx(StringHelp::utf8_to_ucs2(filenam e).c_str(), FR_PRIVATE|FR_NOT_ENUM, 0);

and I'm wondering if this will work in windows in a zipped resource file?

rombust
11-03-2013, 08:03 PM
By the way, I was looking at the Font Engine for win32 code, like this:

AddFontResourceEx(StringHelp::utf8_to_ucs2(filenam e).c_str(), FR_PRIVATE|FR_NOT_ENUM, 0);

and I'm wondering if this will work in windows in a zipped resource file?

No, it will not work. Although it should be easy to fix.

Instead of usng AddFontResourceEx, use AddFontMemResourceEx

Loading the font into a clan::DataBuffer,


DataBuffer data(file.get_size());
file.read(data.get_data(), data.get_size());
int out_number_of_fonts = 0;
HANDLE handle = AddFontMemResourceEx(data.get_data(), data.get_size(), 0, &out_number_of_fonts);Imho, you should not need to call: RemoveFontMemResourceEx(handle); since it's unloaded automatically when the application exits. I'm unsure about repeated calls to AddFontMemResourceEx using the same font, but, it "should" be okay and "ignore" the subsequent calls


( http://msdn.microsoft.com/en-us/library/windows/desktop/dd183325(v=vs.85).aspx )

Nightwind0
11-04-2013, 10:57 PM
No, it will not work. Although it should be easy to fix.

Instead of usng AddFontResourceEx, use AddFontMemResourceEx

Loading the font into a clan::DataBuffer,


DataBuffer data(file.get_size());
file.read(data.get_data(), data.get_size());
int out_number_of_fonts = 0;
HANDLE handle = AddFontMemResourceEx(data.get_data(), data.get_size(), 0, &out_number_of_fonts);Imho, you should not need to call: RemoveFontMemResourceEx(handle); since it's unloaded automatically when the application exits. I'm unsure about repeated calls to AddFontMemResourceEx using the same font, but, it "should" be okay and "ignore" the subsequent calls


( http://msdn.microsoft.com/en-us/library/windows/desktop/dd183325(v=vs.85).aspx )


Oh, cool. Are you going to patch the Win32 font engine with that?

Nightwind0
11-17-2013, 02:18 AM
So, I thought your earlier patch fixed my problem, but it only fixes it in certain situations (when your working directory is the same as where resources are). I see the real problem, which is that when we load most resources, the FileSystem object gets passed around so that the file can be loaded from it. However, in the case of TTF Fonts, we don't do that, we only pass a filename.
Is there a way we can do that, and implement the fonts using the memory based Win32 font API and the Freetype for Linux? I really need to be able to package my TTF fonts into a zip, and I currently can't do that.













No, it will not work. Although it should be easy to fix.

Instead of usng AddFontResourceEx, use AddFontMemResourceEx

Loading the font into a clan::DataBuffer,


DataBuffer data(file.get_size());
file.read(data.get_data(), data.get_size());
int out_number_of_fonts = 0;
HANDLE handle = AddFontMemResourceEx(data.get_data(), data.get_size(), 0, &out_number_of_fonts);Imho, you should not need to call: RemoveFontMemResourceEx(handle); since it's unloaded automatically when the application exits. I'm unsure about repeated calls to AddFontMemResourceEx using the same font, but, it "should" be okay and "ignore" the subsequent calls


( http://msdn.microsoft.com/en-us/library/windows/desktop/dd183325(v=vs.85).aspx )

rombust
11-17-2013, 10:27 AM
I can't see a reason not to do that. The API would need to change, but I don't see that's a problem.

I'm not sure how hard it would be to implement, in theory it should be easy.

Nightwind0
11-17-2013, 09:55 PM
Okay, I've gone ahead and done that. I'm including a zip file with the files I changed.

I had to add one constructor to Font. I tested my patch under Linux and it works, and I made sure that it compiles in Win32 but I haven't actually tried the Win32 version (which uses AddFontMemResourceEx), however, I based it on the code you posted earlier in this thread, and it should work.




I can't see a reason not to do that. The API would need to change, but I don't see that's a problem.

I'm not sure how hard it would be to implement, in theory it should be easy.

rombust
11-18-2013, 08:39 AM
Patch applied. Many thanks