IrrFontTool Linux implementation
IrrFontTool Linux implementation
Hello all,
I got into Irrlicht recently, and I found I needed a bitmap font. I tried building the new IrrFontTool under Ubuntu 64bit and although it compiled, I got that unpleasant message "os not supported", so I've written the code necessary to make it work under Linux.
The work is done, and I'll release it as soon as I can test it, however, I can't test it due to what I think is a bug in Irrlicht's XML writer/reader. XML files produced by the writer have 4 bytes per character (sizeof wchar_t on 64bit Linux), but Irrlicht cannot read them because it seems to expecting only 2 bytes per character. Files produced on the 32bit windows version only have two bytes per character and can be opened successfully.
I'll post this to the bug forum to see if I can some feedback on the problem.
I got into Irrlicht recently, and I found I needed a bitmap font. I tried building the new IrrFontTool under Ubuntu 64bit and although it compiled, I got that unpleasant message "os not supported", so I've written the code necessary to make it work under Linux.
The work is done, and I'll release it as soon as I can test it, however, I can't test it due to what I think is a bug in Irrlicht's XML writer/reader. XML files produced by the writer have 4 bytes per character (sizeof wchar_t on 64bit Linux), but Irrlicht cannot read them because it seems to expecting only 2 bytes per character. Files produced on the 32bit windows version only have two bytes per character and can be opened successfully.
I'll post this to the bug forum to see if I can some feedback on the problem.
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Excellent, thanks for looking into this. Yes, wchar_t is not my favourite type; it's entirely compiler dependent.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
I'm going to go ahead and log that wchar_t thing as a bug.
I created a small hack to get around the problems with the XML writer. I was then able to test the Font Tool code and I'm happy with it, so I've posted it to the tracker as a patch.
https://sourceforge.net/tracker2/?func= ... tid=540678
I've added a comment to the patch with the hack code in it for any 64 bit Linux users.
Testing and feedback is welcomed
I created a small hack to get around the problems with the XML writer. I was then able to test the Font Tool code and I'm happy with it, so I've posted it to the tracker as a patch.
https://sourceforge.net/tracker2/?func= ... tid=540678
I've added a comment to the patch with the hack code in it for any 64 bit Linux users.
Testing and feedback is welcomed
yes, i am. thanks.for any 64 bit Linux users.
My company: http://www.kloena.com
My blog: http://www.zhieng.com
My co-working space: http://www.deskspace.info
My blog: http://www.zhieng.com
My co-working space: http://www.deskspace.info
First of all, thanks very much for doing this. It's much appreciated.
Secondly, I've had a series of segfaults while using it, but I've figured out why they happen. It seems as though it's possible to enter the inner 'rasterizing' loops of makeBitmapFont() [lines 637 to 659 in the patched CFontTool.cpp] with a 'chWidth' value of zero.
The chHeight and chWidth values come from the dimensions of the current fontArea's rectangle [line 623] and are passed to XGetImage() to create the XImage for the font [line 636]. XGetImage() will return null when there's a problem (which there will be with a zero dimension). When "image->f.destroy_image(image);" is then called on line 660, it's trying to dereference a null pointer, which causes the crash.
Wrapping a null-guard around the destroy_image() call ...
if(image != NULL) { image->f.destroy_image(image); }
... is probably the cheapest way to prevent the crash and keep it working (the rasterizing will never occur with a zero dimension anyway, so we don't have to worry too much about it -- a couple of unnecessary trips around the outer for-loop aside), but this doesn't solve the issue of why zero dimensions are cropping up to begin with. I haven't looked much deeper at that but it could be a 'feature' from the fonts themselves.
Secondly, I've had a series of segfaults while using it, but I've figured out why they happen. It seems as though it's possible to enter the inner 'rasterizing' loops of makeBitmapFont() [lines 637 to 659 in the patched CFontTool.cpp] with a 'chWidth' value of zero.
The chHeight and chWidth values come from the dimensions of the current fontArea's rectangle [line 623] and are passed to XGetImage() to create the XImage for the font [line 636]. XGetImage() will return null when there's a problem (which there will be with a zero dimension). When "image->f.destroy_image(image);" is then called on line 660, it's trying to dereference a null pointer, which causes the crash.
Wrapping a null-guard around the destroy_image() call ...
if(image != NULL) { image->f.destroy_image(image); }
... is probably the cheapest way to prevent the crash and keep it working (the rasterizing will never occur with a zero dimension anyway, so we don't have to worry too much about it -- a couple of unnecessary trips around the outer for-loop aside), but this doesn't solve the issue of why zero dimensions are cropping up to begin with. I haven't looked much deeper at that but it could be a 'feature' from the fonts themselves.
Thanks for the feedback!
I suspect it's a feature of that particular font since I found a few of my fonts had zero width and zero height characters. I'm using the xOff of the character to work out it's width (line 525) - this is the distance from the left edge of the character to the left edge of the next. I'm betting that your font has a character with an xOff of -1, so it passes the width != 0 test, then because it's anti-aliased, it's padded with 1 pixel, so -1 + 1 = 0, and there's your zero width.
Seems I might need to check for zero width after padding, though it could be that I need to use a different method to work out the width. Can you upload the font somewhere so I can take a look at the character? And what font point size were you using, because that might be a factor too. Thanks.
I suspect it's a feature of that particular font since I found a few of my fonts had zero width and zero height characters. I'm using the xOff of the character to work out it's width (line 525) - this is the distance from the left edge of the character to the left edge of the next. I'm betting that your font has a character with an xOff of -1, so it passes the width != 0 test, then because it's anti-aliased, it's padded with 1 pixel, so -1 + 1 = 0, and there's your zero width.
Seems I might need to check for zero width after padding, though it could be that I need to use a different method to work out the width. Can you upload the font somewhere so I can take a look at the character? And what font point size were you using, because that might be a factor too. Thanks.
I'm not at the machine in question right now, but I did manage to find settings which failed every time (prior to the null-guard kludge) so used these to find out what was wrong.
On my machine it was:
Charset: monotype
Font: Arial
Size: 20px
Bold: True (all other options False)
MaxWidth: 512
MaxHeight: 1024
Filename: anything
File Format: bmp
I think it's the standard MS Arial font from the corefonts package, but would have to check my exact font set-up to be sure.
On my machine it was:
Charset: monotype
Font: Arial
Size: 20px
Bold: True (all other options False)
MaxWidth: 512
MaxHeight: 1024
Filename: anything
File Format: bmp
I think it's the standard MS Arial font from the corefonts package, but would have to check my exact font set-up to be sure.
I've installed the ms fonts, but I can't reproduce the problem. Maybe I've got a different version of the fonts than you? I'm running Ubuntu 8.10. My version of Arial has 1187 characters according to the output from FontTool.
Anyway, I've made two changes to the code. First, I've changed the check for a zero width and height to a check for a width and height that's less than or equal to zero. Secondly, I've wrapped the image creation in a NULL check.
Anyway, I've made two changes to the code. First, I've changed the check for a zero width and height to a check for a width and height that's less than or equal to zero. Secondly, I've wrapped the image creation in a NULL check.
For anyone trying this out, please note that it seems that anti-aliasing can't be turned off even if the checkbox is not checked. On my system at least, Xft, which is used to render the fonts, ignores the anti-alias option when selecting a font and defaults it to true.
Freetype2 is another font renderer and that can only produce aliased fonts, but they looked awful in my testing so I didn't bother implementing it into the code.
This means that you'll only really be able to produce fonts about 8 or more pixels in size because anything less than that and the characters start to become a bit blurry.
Freetype2 is another font renderer and that can only produce aliased fonts, but they looked awful in my testing so I didn't bother implementing it into the code.
This means that you'll only really be able to produce fonts about 8 or more pixels in size because anything less than that and the characters start to become a bit blurry.
I'm having trouble applying the new patch. Against both the original newFontTool directory and a 1st-patch-applied newFontTool directory, I get "Reversed (or previously applied) patch detected!" complaints from patch, with every option then leading to some failures. Did you diff off a clean directory or had you altered something (working from SVN source?)?
Arial with 1187 characters is exactly what I get here. I tracked it down and it is indeed Arial from the MS fonts (the exact package is "ttf-ms-fonts-2.0-1" from the Arch repositories, available here if you want it). To be honest, though, I doubt it'll be any different to the one you've already got. I imagine it's more a question of exactly which X11 font drivers you've got loaded at any given time. I'm currently using freetype2, and not xft. I imagine that this is where the differences are coming from.
As to the aliased / anti-aliased thing, I have the opposite issue (probably freetype again) in that nothing seems anti-aliased, whether antialiasing is checked or not. Hmmm, wait a minute. I wonder if KDE is having an effect ...
OK. It seems as if (at least with freetype) Linux FontTool's support for anti-aliasing depends entirely on the state of the font server at the given point in time and has little to do with the checkbox or code value. Changing the anti-alias settings in KDE (which I'm fairly sure just calls X) changes the anti-alias effect in FontTool at the point where FontTool is started up. If you turn on anti-aliasing at the Desktop level, then start FontTool, everything in FontTool will be anti-aliased; likewise starting FontTool with anti-aliasing off means you won't get it at all for the duration of FontTool's execution. Whether this is a feature of KDE's X integration or X itself (or freetype) is unclear at this point, but that's what happens. I guess it makes a kind of sense: the app won't see it (or show it) unless it's enabled in the server to start with.
Arial with 1187 characters is exactly what I get here. I tracked it down and it is indeed Arial from the MS fonts (the exact package is "ttf-ms-fonts-2.0-1" from the Arch repositories, available here if you want it). To be honest, though, I doubt it'll be any different to the one you've already got. I imagine it's more a question of exactly which X11 font drivers you've got loaded at any given time. I'm currently using freetype2, and not xft. I imagine that this is where the differences are coming from.
As to the aliased / anti-aliased thing, I have the opposite issue (probably freetype again) in that nothing seems anti-aliased, whether antialiasing is checked or not. Hmmm, wait a minute. I wonder if KDE is having an effect ...
OK. It seems as if (at least with freetype) Linux FontTool's support for anti-aliasing depends entirely on the state of the font server at the given point in time and has little to do with the checkbox or code value. Changing the anti-alias settings in KDE (which I'm fairly sure just calls X) changes the anti-alias effect in FontTool at the point where FontTool is started up. If you turn on anti-aliasing at the Desktop level, then start FontTool, everything in FontTool will be anti-aliased; likewise starting FontTool with anti-aliasing off means you won't get it at all for the duration of FontTool's execution. Whether this is a feature of KDE's X integration or X itself (or freetype) is unclear at this point, but that's what happens. I guess it makes a kind of sense: the app won't see it (or show it) unless it's enabled in the server to start with.
I recreated the patch and checked it against a fresh copy of the repo, so hopefully this one is OK.
Xft is a layer on top of FreeType2 that provides the ability to use anti-aliasing which FreeType2 can't do.
So something in the OS is controlling the anti-aliasing. I'll try playing with the font rendering settings in Ubuntu to see if I can get the same effect. There must be a way of overriding it.
Xft is a layer on top of FreeType2 that provides the ability to use anti-aliasing which FreeType2 can't do.
So something in the OS is controlling the anti-aliasing. I'll try playing with the font rendering settings in Ubuntu to see if I can get the same effect. There must be a way of overriding it.
It appears that the anti-alias settings are system wide and cannot be overridden on a per-application basis. It turned on automatically on my system because I'm using an LCD monitor connected via DVI.
Remember that all changes to /etc/fonts/local.conf are system wide and will be overridden by ~/.fonts.conf, except for the anti-aliasing setting which will be forced on if set in the system wide file.
Patch works. Thanks.
That makes sense. I found this in the Xorg docs:
A tangential finding was that, if Xft-powered anti-aliasing is on when you create a font, you have to enable alpha on the font, otherwise the bit-mapping occludes the semi-transparent pixels wholly and the font looks horrible in irrlicht.
That makes sense. I found this in the Xorg docs:
So in KDE's case it's entirely to do with whether Xft is active or not. If not, it uses the core system, so no anti-aliasing whatever the setting. If active, it seems everything gets anti-aliased by default because that's its global state.For KDE applications, you should select ``Anti-alias fonts'' in the ``Fonts'' panel of KDE's ``Control Center''. Note that this option is misnamed: it switches KDE to using Xft but doesn't enable anti-aliasing in case it was disabled by your Xft configuration file. -- here
A tangential finding was that, if Xft-powered anti-aliasing is on when you create a font, you have to enable alpha on the font, otherwise the bit-mapping occludes the semi-transparent pixels wholly and the font looks horrible in irrlicht.
The same thing happens to fonts rendered in the Windows version of FontTool. There's no way to change this behavior short of forcing transparency on when aa is checked.A tangential finding was that, if Xft-powered anti-aliasing is on when you create a font, you have to enable alpha on the font, otherwise the bit-mapping occludes the semi-transparent pixels wholly and the font looks horrible in irrlicht.
So, in the end, it seems if people want aliased or anti-aliased fonts they're going to have to change the global settings for their OS then restart FontTool. I think I need to put a message box or something into FontTool with a warning about this.
Thanks for the help working this out.