Results 1 to 8 of 8

Thread: Suggestions for modification to the ClanLib 0.9 Font API

  1. #1
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default Suggestions for modification to the ClanLib 0.9 Font API

    These are my suggestions for modifications to the ClanLib 0,9 Font API - with the aim to support bitmap fonts (cached truetype or user created)

    // Change this to an interface (virtual pure functions) containing:
    Class CL_Font

    // Draw the font to the screen
    Draw(CL_GraphicContext, text to draw, xpos, ypos, color)

    // Draw the font to a pixelbuffer
    Draw(CL_GraphicContext, CL_PixelBuffer, text to draw, xpos, ypos, color)

    // Retreive the size of the font
    CL_Size Size(CL_GraphicContext, text to use)
    // This contains the TrueType fonts, either Microsoft API native fonts or Freetype fonts (for linux)
    // The code should be taken out of "opengl_graphic_context_provider.cpp" (as it is does not require opengl)
    Class CL_TruetypeFont : public CL_Font

    // Create the font (using the current method)
    Create(typeface_name, height, average_width...);
    // This contains bitmap fonts (using CL_Texture)
    Class CL_BitmapFont : public CL_Font

    // Create using the typetype font, writing into CL_TextureGroup using the truetype pixel buffer
    // Create CL_SubTexture's for all in glyph list (and/or add/create them dynamically)
    // In effect this will cache the CL_TruetypeFont's
    Create( CL_TruetypeFont &ttf, glyph list)

    // Create using the user suppled bitmap's
    Create( List of CL_SubTexture &tg, glyph list)

  2. #2
    Master Sorcerer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    A font isn't just a font. The three font types, true-type, vector and bitmap are quite different in behavior.

    A bitmap font scaled by 2 is exactly twice as tall and wide, while a true-type font's hinting causes a true-type font to change its size in a less predictable way. A bitmap font generally consists of a limited set of glyphs, while a true-type font often have many thousand glyphs. Vector fonts contain no hinting and are generally generated for a certain range of resolutions - i.e. you may want to control how many triangles it uses to describe curves. Text metrics are generally also more details for true-type fonts than for bitmap and vector fonts.

    The usage patterns of each font type is generally also different. You use bitmap fonts limited places where the user does not affect the text used - it might be some text where each glyph has blood dripping from it in an animated way. Vector fonts are typically used in situations where want to rotate and scale them in a fast way, maybe with vertex and fragment shaders. For traditional "boring" places where you want to support text from all nations you resort to true-type fonts.

    The current model separates these three font types because of their different traits and usage patterns. While certain functions could be kept in a shared CL_Font interface derived by the other font types, I am personally not that much a believer into interface oriented design. The downside of linking them like that means that you add dependency between them, locking them down to having to follow the same base perception of what a font is and what you use it for. A simple example of problems that might arise is if we add text services support for the true-type font rendering system - if we added that to the basic CL_Font, we would have to make bitmap and vector fonts compatible to that as well. If we don't add it, the CL_Font class becomes a primitive abstraction that no longer fits true-type font rendering that well anymore. Furthermore, true-type font metrics change based on your gc and the scaling applied, while they don't for the two other types - so you could not simplify the functions for bitmap and vector because you'd have to adjust for the true-type font complexity as well.

    All that said, it can be argued whether the current true-type font functions should be tied directly into the gc, or if they should be put outside like the bitmap and vector fonts. There are both advantages and disadvantages to that as well, of course. I.e. a "metafile" recorder would not be able to record the text drawing commands directly if it was separated from the gc.

  3. #3
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Yes, I agree with you that the 3 font types behave quite differently.

    I can see the disadvantages of my proposal, one of them would have been a show-stopper, as I will explain below.

    However the objective of fonts is the same, to display text onto the screen.

    The aim was to be able to have finer control of which fonts the ClanLib GUI uses, though a consistent interface.

    As I understand it, this is what ClanLib currently does:

    CL_Font allocates the font using the current context provider:

    In the case of CL_OpenGLGraphicContextProvider, this creates CL_OpenGLFontProvider that creates an internal font handle (Windows CreateFont() or FreetypeFont)

    The font to set using the CL_GraphicContext::set_font()

    The font is drawn using CL_GraphicContext::draw_text()
    In the case of CL_OpenGLGraphicContextProvider, draw_text() :
    Windows: Use the window handle to select the font. I believe that is the main reason that the Windows API font cannot be separated from OpenGL. Create a pixel buffer, and use draw_pixels().

    Linux: Create a FreetypeFont pixel buffer, and draw_pixels().

    My line of thought was that it is a waste to recreate the pixel buffer for each glyph to be drawn in time critical situations. An optional alternative is to store the glyphs in a cache (using CL_TextureGroup) - ie a CL_BitmapFont. The number of glyphs to store would depend on the text to be drawn. If only the ASCII character set is required (not including Unicode chars), you could pack 64, 32x32 glyphs into a single 256x256 texture (enough for 0-9a-zA-z).

    I suppose that in reality, the developers using ClanLib would design there own font anyway, but it could be a simple extension to CL_BitmapFont to import CL_FreetypeFont glyphs

    This is my second proposal:

    Class CL_BitmapFont
    // Set a user defined bitmap font
    Set( List of CL_SubTexture’s, List of glyphs matching the sub textures)


    DrawText( CL_GraphicContext, x, y, text, color)
    GetGlyph( glyph,
    where to write the address of the CL_SubTexture,
    position info of subtexture.

    With this possible extension:
    Class CL_BitmapFont

    // Create a bitmap font, based on the current selected graphic context font
    Create( CL_GraphicContext bitmap_context (to create CL_TextureGroup),
    CL_GraphicContext font_context (where the font is located),
    Required text letters to form glyphs

    Class CL_GraphicContext

    CL_PixelBuffer Create_Text( text, color, anti_alias,
    CL_Point &dest_offset,
    CL_Point &dest_increment)

    There is still the problem on how to select a user-defined font into the GUI. An option could be

    Class CL_GraphicContext

    Set_font(CL_Font) // Set the standard font
    Set_font(CL_VectorFont) // Set a vector font
    Set_font(CL_BitmapFont) // Set a bitmap font

    I have not looked into this, but I think it should work? humm but it is restrictive ... you don't want to have to modify CL_GraphicContext to insert CL_MyAnimatedRaytracedFont with many parameters

    (Maybe CL_TextureFont is a better name to CL_BitmapFont ?)
    Last edited by rombust; 08-10-2007 at 11:19 AM.

  4. #4
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Here is my example implementation of the above method.
    screengrab.png --> Program output
    test.txt --> "test.cpp" from my Font2 test
    newpatch.txt --> svn patch required (excluding Font2 test)
    font.png --> Bitmap font required for test.cpp

    Note: The CL_TextureFont API is inside test.cpp (not the svn patch)

    (Last edited 1:30PM Thursday 16th August)
    Attached Images Attached Images   
    Attached Files Attached Files
    Last edited by rombust; 08-16-2007 at 03:48 PM. Reason: Modified example

  5. #5
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Smile

    I would like to apply the svn patch (which implements the get_font_glyph() function) - It is proving awkward doing a "selective commit" to svn for other minor changes

    And in the meantime, commit the "Font2" example (which includes the CL_TextureFont classes), until it has been decided if it should be included in the main clanlib api

    *Note*
    I am not sure that I have correctly differentiated between glyph and character. I think the current implementation, get_font_glyph() should be replaced by get_font_character()
    Last edited by rombust; 08-16-2007 at 08:30 PM.

  6. #6
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    I have had second thoughts on my patch. What is concerning me (through my past experience of Amiga demo programming), is that there are numerous methods of handling fonts. I am not entirely sure that my class would be helpful as a part of the API. It may be better to leave it as an example. The code is very simplistic, and can be adapted to the developers needs.

    Instead, apply the get_font_character() function to the API, to enable the developer to obtain the font character pixel buffer.

    And I will tidy up the Font2 example, and put it into Tests/Display/Font2.

  7. #7
    Master Sorcerer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    Your patch is definitely interesting, but I need to gather a little mental energy to read it and comment on it. Although this may seem strange that I can code a lot of clanlib stuff, and at the same time take a very long time to comment someone's patch, it is because design decisions are a lot harder to context switch to and give a reasonable feedback upon.

    The stuff you implement, such as the glyph texture cache, is something we need to have. The current font implementation which allocates a system memory buffer for each glyph, then asks the font library to render the glyph, and finally forwards it to OpenGL is obviously not a very efficient method.

    I do find it fairly difficult to solve these issues, since I haven't really truly decided whether I think the CL_GraphicContext::draw_text routine should use textures or pixel buffers to draw text.

    The current loss of speed isn't so much because of glyphs not being in texture memory, but simply the fact that we generate the glyph bitmap and allocate the memory each and every time we need to draw one, instead of fetching them from a cache. Modern GPUs draw raster graphics pretty fast, but of course it still has to stream the data over the bus if we cache it in system memory. On the other hand, if we cache it in a texture we get the usual problems of having to decide the size of the texture, how we want to populate the texture with glyphs and so on.

    The theoretically fastest rendering technique is to store the glyphs in a texture, the vertex data and the element array indicies in GPU memory. But the more we change this data, the bigger is the question whether we gained enough to outweight the disadvantage of having all your data remote.

    So far my strategy has been to postpone these problems until the various systems inside ClanLib that handle buffer objects, textures and vertex data has matured further. The current implementations goals has only been to provide text for clanGUI so we wouldn't be show stopped by it, but of course if you feel up for the task to try upgrade it to be fast or smart as well, I'm all okay with the idea.

    All this of course also opens the question whether the (texture) glyph cache should share functionality with the pure bitmap fonts, if CL_TextureGroup should be involved, and if it should be exported to API level or not.

    Since this is an area where a lot of ideas can be tested (and possibly be regretted), I recommend you use the shelf system in the svn directory structure, instead of supplying patches for stuff you are uncertain if should be applied or not yet.

    The general idea of the shelf directory structure is that you can copy the main branch (ClanLib/Development/ClanLib-0.9) to a shelf directory that you name, i.e. ClanLib/Shelves/FontTextureCache, and apply your changes here. We can then very easilly switch to this shelf using svn switch, test, modify and evaluate. The key advantage is that you still get svn to handle your patches, we don't break the main branch, and we can merge the shelf back into main when we feel it is ready (or delete the shelf completely if we regret the entire idea).

  8. #8
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Yeah.

    I have not heard of shelves in svn before, i'll later a look at that later

    In the meantime, i have put the font2 test into svn, as it tests CL_TextureGroup.

    Thanks

Similar Threads

  1. I need help using CL_Font with a System font on the Mac
    By eoliveri in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 08-07-2007, 01:59 PM
  2. A few UI suggestions and possibly a bug..
    By loken in forum Novashell Game Creation System
    Replies: 6
    Last Post: 12-23-2006, 01:43 AM
  3. Interface suggestions
    By Uhfgood in forum Novashell Game Creation System
    Replies: 4
    Last Post: 11-16-2006, 06:07 AM
  4. Suggestions, for whenever they might be implemented
    By File Sponge in forum Funeral Quest
    Replies: 2
    Last Post: 10-21-2006, 01:55 AM
  5. Next up date suggestions
    By lancevance in forum Funeral Quest
    Replies: 6
    Last Post: 11-29-2003, 04:39 PM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •