james_lohr's picture

QuickFont

I'd just like to announce the release of QuickFont, a text printing and font generation library: http://www.opentk.com/project/QuickFont

I could only upload 4 images on the project page, so I've uploaded the remaining screenshots here.

Enjoy. :)

James L.

Images

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
james_lohr's picture

>>(2) There's about 5 references making use of Linq that are easily replaced by common .NET 2.0 syntax. Why not get Linq right out of there?

Thank you Emzee, this is an excellent suggestion. I have removed all Linq references, and QuickFont (version 1.0.1 +) now builds in .Net 2.0.

>>(1) Consider a more canonical namespace than just "QuickFont", such as "OpenTK.Library.QuickFont" or eve "JamesLohr.OpenTK.QuickFont"?

Could you explain the advantage of a more canonical namespace please? - Both seem rather clunky compared to just QuickFont.

>> what license are you releasing it under?

The same as OpenTk: basically do whatever you like with it. However, if you have changes that you think would be beneficial for all then do suggest them I will try to get them into the next release. The advantage for you being that you won't have to hack around each new version to include the changes you would like. :)

KimikoMuffin's picture

Well, one thing was vertical-alignment: positioning the string from the bottom up instead of top-down. Maybe more control over character-orientations, too, like how Japanese is traditionally "characters are ordered top-down and lines are arranged right-to-left" where English is "characters left-to-right and lines top-down," but I meant setting it up so the programmer could arrange this however you wanted.

The big thing that's currently on my mind, though, is better unicode support. It's technically easy enough to add more characters to QFontBuilderConfiguration.charSet, but there's nothing for unicode control characters which change the location of the text, which isn't usually going to be a problem for most purposes, but i.e. there's Arabic characters or other bi-directional text which appears "wrong".

(As an aside, my primary motivation for setting this up is so I can have a "dynamic" system for translating my game into multiple languages; it's not a bit issue for French and Spanish, or even Russian and Japanese, but I discovered by chance that it broke Arabic while I was testing it with Yog-Sothoth's arabic name (يجيء الشذاذ "Yaji Ash-Shuthath," "the abnormal ones are coming") from the Call of Cthulhu RPG, alongside a render of the same text using System.Drawing by itself, and I discovered that the characters in the QuickFont rendition were in the opposite apparent order from the System.Drawing render -- it appeared as ذاذلا ءيجي in QuickFont.)

puklaus's picture

Display list -support for QuickFont 1.0.1:
* add to QFontGlyph.cs:

        /// <summary>
        /// Character's display list
        /// </summary>
        public int DisplayList = 0;

* modified RenderGlyph-method in QFont.cs:

        public void RenderGlyph(float x, float y, char c, bool isDropShadow)
        {
 
 
            var glyph = fontData.CharSetMapping[c];
 
            //note: it's not immediately obvious, but this combined with the paramteters to 
            //RenderGlyph for the shadow mean that we render the shadow centrally (despite it being a different size)
            //under the glyph
            if (isDropShadow) 
            {
                x -= (int)(glyph.rect.Width * 0.5f);
                y -= (int)(glyph.rect.Height * 0.5f + glyph.yOffset);
            }
 
 
            RenderDropShadow(x, y, c, glyph);
 
 
            if (isDropShadow)
            {
                GL.Color4(1.0f, 1.0f, 1.0f, Options.DropShadowOpacity);
            }
            else
            {
                GL.Color4(Options.Colour);
            }
 
 
            TexturePage sheet = fontData.Pages[glyph.page];
            GL.BindTexture(TextureTarget.Texture2D, sheet.GLTexID);
 
            GL.Translate(x, y, 0);
            if (glyph.DisplayList == 0)
            {
                glyph.DisplayList = GL.GenLists(1);
                GL.NewList(glyph.DisplayList, ListMode.CompileAndExecute);
 
                float tx1 = (float)(glyph.rect.X) / sheet.Width;
                float ty1 = (float)(glyph.rect.Y) / sheet.Height;
                float tx2 = (float)(glyph.rect.X + glyph.rect.Width) / sheet.Width;
                float ty2 = (float)(glyph.rect.Y + glyph.rect.Height) / sheet.Height;
 
                GL.Begin(BeginMode.Quads);
                GL.TexCoord2(tx1, ty1); GL.Vertex2(0, glyph.yOffset);
                GL.TexCoord2(tx1, ty2); GL.Vertex2(0, glyph.yOffset + glyph.rect.Height);
                GL.TexCoord2(tx2, ty2); GL.Vertex2(glyph.rect.Width, glyph.yOffset + glyph.rect.Height);
                GL.TexCoord2(tx2, ty1); GL.Vertex2(glyph.rect.Width, glyph.yOffset);
                GL.End();
 
                GL.EndList();
            }
            else
                GL.CallList(glyph.DisplayList);
 
            GL.Translate(-x, -y, 0);
        }

* somewhere when disposing:

//foreach glyph
            GL.DeleteLists(glyph.DisplayList, 1);
            glyph.DisplayList = 0;

Note:
display lists might not work on linux in VM, at least I didnt got these to work last year, but then I just temporaly disabled creating lists because I used VM only testing.

c2woody's picture

Thanks for picking up this by times tricky and demanding topic of text rendering, nice there's somebody maintaining it and coming up with nice ideas. The sample code looks impressive!

KimikoMuffin's picture

Aha -- this might be useful for the bi-directional purposes!

EDIT: Also, I just added the following to QFont.cs just because it made sense to have it, as well as making the QFont class itself implement IDisposable:

        #region IDisposable Implementation
        private bool _disposed = false;
 
        /// <summary>
        /// True if the QFont has been disposed; false otherwise.
        /// </summary>
        public bool IsDisposed
        {
            get { return _disposed; }
        }
 
        /// <summary>
        /// Dispose of the QFont data.
        /// </summary>
        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
 
                fontData.Dispose();
 
                optionsStack.Clear();
            }
        }
        #endregion
Maverick's picture
yehiyam wrote:

Hi
I'm looking into using QuickFont in my project.
Looking at the code I couldn't find if you have written support for right-to-left strings.
Is it something that you plan on adding in the future?

thanks
Yehiyam

Hi. I'm looking into using OpenTK and Quick Font in my project too and am interested in above question too. I'm doing a windowsform application using GLControl. In my project almos all texts will be non ASCII, so UTF8 support is preferred.

I've tried adding UTF8 text in QuickFont example, but it doesn't show.

Example:
...
mainText = new QFont(new Font("arial", 14), builderConfig);
...
mainText.Print("++ ĂÎŞŢÂăîşţâ ++ ЙЦУКЕНГШйцукенгш ++ abcABC ++"); // --> only pluses and abcABC shows
...

the Fiddler's picture

AFAIK, QuickFont only implements latin text.

Your best bet for non-latin text is to use System.Drawing: render text on a Bitmap, upload it to an OpenGL texture and display that on screen.

KimikoMuffin's picture

The problem with the characters not displaying is probably that Arial didn't support the characters you were using. When constructing with FontFamily.GenericSansSerif instead of string-literal "Arial", the Unicode characters will appear (I've tested this and it works). It still won't do right-to-left text properly, so yeah, Fiddler's got the best bet.

yehiyam's picture

Hi Maverick
For use with Quickfont, you have to specify the characters in advance. Out of the box it only supports latin alpha-numeric+ punctuation.
If I recall correctly, there is a string property of QuickFontBuilderConfig that defines all the characters. Just add your characters and go.
For right to left, I ended up using an open source code called freebidi . Its quite old (around 2007) but it works great.

Yehiyam

Maverick's picture

Tanks, for tips. Will try them all and see what fits my needs better. Although having left-right and UTF8 features as default in QuickFont would've been awesome. :)