Improvements to font handling and rendering

Spire

12-01-2012 00:08:32

For the project I'm currently working on, which uses MyGUI as its UI engine, I've made some fairly extensive modifications to some of the MyGUI font-related code to improve performance and to fix bugs. I would like to contribute these modifications to MyGUI if the MyGUI developers are interested. Now that MyGUI 3.2.0 appears to be nearing official release, it seems like perfect timing to have these modifications considered for inclusion in this release. I have them available in the form of a patch against the latest revision of MyGUI in the repository.

Here's what my patch does:

  1. Dramatically reduces the amount of texture memory used for a TrueType font. It achieves this by doing two things:

    1. Eliminate duplicate glyphs from the font texture in cases where multiple code points use the same glyph. The most common case where this occurs is with the "not defined" glyph.

      [/*:m]
    2. Pack glyphs onto the font texture as tightly as possible by first getting rid of all bearing- and advance-related whitespace, reducing each glyph to its absolute minimum "printable" bounding box. Then arrange all the glyphs by height within the font texture.[/*:m][/list:o]
      Some real-world examples:

      1. Take the "DejaVu Sans" font that is bundled with MyGUI. Instantiating this font at 7 pt (96 PPI) with all supported characters previously resulted in a 1,024×1,024-pixel texture occupying 2 MiB of texture memory; now the exact same font is contained in a 512×512-pixel texture occupying 512 KiB -- a 75% savings.

        Here are "before" and "after" versions of this font texture to illustrate the difference (click for full size):

        [attachment=1]DejaVu Sans 7 pt (96 PPI) - Before.png[/attachment]
        [attachment=0]DejaVu Sans 7 pt (96 PPI) - After.png[/attachment]
        [/*:m]
      2. Instantiating the same "DejaVu Sans" font at 30 pt (96 PPI) with all supported characters previously resulted in a 4,096×4,096-pixel texture occupying 32 MiB of texture memory; now the exact same font is contained in a 2,048×2,048-pixel texture occupying 8 MiB.

        [/*:m]
      3. Finally, take the "MingLiU" font that comes with Windows 7. It's a monster 30 MiB font containing many thousands of glyphs. Instantiating this font at 14 pt (96 PPI) with all supported characters previously resulted in a 8,192×4,096-pixel texture occupying 64 MiB of texture memory; now the exact same font is contained in a 4,096×4,096-pixel texture occupying 32 MiB.[/*:m][/list:u]
        As you can see, this improvement lowers the GPU system requirements for any MyGUI application that uses fonts. It also makes it possible to use fonts and font sizes that were previously impossible due to running out of texture memory.

        [/*:m]
      4. Improves the performance of ResourceTrueTypeFont::initialise() by using internal template classes and functions to perform compile-time branching. Previously the code was branching on invariants such as mAntialiasColour and rgbaMode many thousands of times inside tight loops. Now all of this branching is done once -- and only once -- at the very start of initialization. This significantly decreases application startup time, especially when large fonts are in use. Using the above example of the MingLiU font at 14 pt (96 PPI), initialization time has been reduced from 1.3 seconds to 0.8 seconds (running on my Core-i7-2600K-based development machine in Release mode).

        [/*:m]
      5. Improves the runtime performance of ResourceTrueTypeFont::getGlyphInfo() by using a single consolidated code-to-glyph map instead of multiple vectors of included and excluded ranges of code points. This makes glyph lookup an O(log n) operation instead of O(n) (or in some cases, even worse). Because ResourceTrueTypeFont::getGlyphInfo() is called all the time during text layout and rendering, this makes MyGUI applications run faster.

        [/*:m]
      6. Adds support for TrueType fonts that contain embedded "SBIT" bitmaps. Many TrueType fonts include such pre-rendered bitmaps for use at specific sizes; these bitmaps are then used instead of the usual splines. Previously any embedded bitmaps would be rendered as unreadable garbage, which was an unwelcome surprise if you happened to choose a font size that used bitmaps; now they are always rendered correctly.

        [/*:m]
      7. Fixes line-spacing calculations. Instead of arbitrarily basing the line spacing on the tallest glyph that is currently in use, the code now uses the metrics directly from the font, which are set by the font designer. Not only is this more typographically correct and more aesthetically pleasing, it is also consistent with other applications. Perhaps more importantly, it prevents the layout of the application from shifting around unpredictably when glyphs are added to or removed from a font definition.

        [/*:m]
      8. Fixes glyph bounding-box calculations. Rendered glyphs are now guaranteed to never overlap inside the font texture under any circumstances; consequently, the "Distance" property of the "ResourceTrueTypeFont", which was cumbersome and error-prone to use, is now deprecated and ignored. A warning is issued to the MyGUI log when this property is used.

        [/*:m]
      9. Fixes handling of whitespace characters. Previously the ResourceTrueTypeFont code would reject any glyph that FreeType delivered with a null bitmap, even though this is normal and correct behavior for any character whose glyph is pure whitespace, such as "Space" (32), "Non-Breaking Space" (160), and many more.

        The ResourceTrueTypeFont code previously provided special handling specifically for the "Space" character in order to work around this problem, but this required that the user manually specify the width of that character using the "SpaceWidth" property. Even with this workaround in place, however, all other whitespace characters would still be broken and could not be used at all.

        Now all whitespace characters are handled correctly, so the "SpaceWidth" property is no longer needed. For backward-compatibility reasons it can still be used, but it is now deprecated with a warning message. Omitting this property causes the width of the "Space" character to be automatically calculated using typographically correct values directly from the glyph metrics.

        [/*:m]
      10. Uses the standard "Not Defined" glyph as a substitute for code points that are not defined in the current font. (This glyph usually looks like a square.) Previously the code would use a "Space" glyph, which is not only non-standard but also provides no obvious indication to the user or to application developer that a glyph is actually missing.

        [/*:m]
      11. Fixes problems with the handling of glyph bearing and horizontal width. Previously, sequences of consecutive overlapping characters, such as "fj", would be rendered incorrectly with the overhanging portions of one or more glyphs clipped by neighboring glyphs. Now glyphs always correctly overlap. Related problems in calculations involving cursor positioning and word wrap have also been corrected accordingly.

        [/*:m]
      12. Implements subpixel positioning. This significantly improves the overall apperance and "color" of text, especially at small sizes and in even more so in pathological cases where a widget has overridden a font's height by setting the "FontHeight" property to a low value. For example, in cases where spacing in between glyphs is supposed to be around 1.5 pixels, the code would previously sometimes use 1 pixel and sometimes use 2, resulting in very uneven spacing. This problem no longer occurs at all, as some portions of horizontal text layout are now performed internally using floating point.

        Note that the use of floating point for some calculations does not appreciably hinder application performance. In fact, extensive benchmarking has shown that the overall performance of the font layout and rendering code is still much higher than before.

        [/*:m]
      13. Provides reasonable defaults for several properties of "ResourceTrueTypeFont". For example, when omitted, "Resolution" now defaults to "96", which is the de facto standard default screen resolution used almost everywhere. Also, "TabWidth", when omitted, defaults to the width of eight "Space" characters. These changes make font definitions simpler and cleaner to read and write.

        [/*:m]
      14. Makes code ranges much simpler to specify. Previously the application developer would have to painstakingly specify which ranges of code points to include and which ones to exclude. This was of vital importance because failing to exclude undefined ranges of code points could cause the font texture to be filled up with unused garbage and become huge; however, there was no easy way to determine which ranges needed to be excluded in this way.

        Although it is still possible to include and exclude code ranges, a developer who simply wants to include everything that the font provides can now simply specify a single range of "0 65535" with no exclusions. The code is smart enough to automatically skip over undefined glyphs and not any waste space in the resulting font texture.

        [/*:m]
      15. Miscellaneous code cleanup. This patch eliminates unnecessary duplicated code in several key areas by moving it into functions and function templates. This process of doing so has also uncovered some bugs involving inconsistencies between duplicated sections of code that should have been the same. Those bugs are now fixed, and the code is now easier to maintain now that the logic occurs at a single point rather than being copy-pasted in several places. Some sporadic crashes caused by insufficient error checking and incorrect calculations have also been fixed.[/*:m][/list:o]
        I think that about covers it -- thanks for reading this far! Please note that although these changes are extensive, they have been heavily tested, used, and refined for quite a while now by both me and my development team. I believe that they are of high enough quality to be released and contributed to the official library. In anticipation of this, I've tried to conform to MyGUI's coding and style conventions as closely as possible. Please let me know if you are interested in evaluating this patch for the purposes of possible inclusion in MyGUI 3.2.0.

Altren

12-01-2012 19:58:55

Hi. Your changes looks interesting, and we are waiting for patches. I'm not sure that we will include them all, since some changes like optimisations that makes code more complex and gives some better speed where nobody cares about it. This is just my assumption and may be I'm wrong.
All changes sounds good except two things:
1. As far as I understand you implemented your own fonts packing algorithm. I wonder why you not used any existing one, since I seen many packing variants. Also main reason of having so big margins is giarantee that you will never see white pixel on glyph's edge, that comes from another adjacent glyph.

2. While standard "Not Defined" and is useful for developers I believe that spaces are more user friendly and clear for them. Best variant is making that "Not Defined" taken from font's description, with space or square by default and possibility to use any other character.

Spire

12-01-2012 21:40:35

Thanks for your reply, Altren. I was waiting to see if you were interested before actually submitting the patch. I'll upload it to SourceForge later today if time permits.

Hi. Your changes looks interesting, and we are waiting for patches. I'm not sure that we will include them all, since some changes like optimisations that makes code more complex and gives some better speed where nobody cares about it. This is just my assumption and may be I'm wrong.
I understand your concern regarding code complexity; I share the same philosophy. IMO my changes actually make the code less complex by making it more modular and less repetitive, but everyone is different and of course your opinion may differ.

I consider the performance improvements to be substantial. When loading a single font with a lot of characters adds 1.3 seconds to application startup time (on a very fast machine), a savings of 0.5 seconds is a lot. And runtime performance is a lot better too due to much faster glyph lookup.


1. As far as I understand you implemented your own fonts packing algorithm. I wonder why you not used any existing one, since I seen many packing variants.

I implemented my own algorithm because my application needs to use several large fonts with a lot of characters, and being able to fit such a font in 8 MiB of precious texture memory instead of 32 MiB without any loss of quality is critical to me. I can't afford to increase my minimum system requirements just to be able to display text in multiple languages.

I've noticed that other people have experienced the same issue as well: 1, 2, 3. I hope my patch will be able to help solve their problems.


Also main reason of having so big margins is giarantee that you will never see white pixel on glyph's edge, that comes from another adjacent glyph.

The reason the white pixels from adjacent glyphs used to appear is that the bounding-box calculations were done without taking certain things into account, such as negative X and Y bearing and cases where the advance is less than the width. Now that I have fixed these calculations the glyphs will never overlap inside the texture no matter what. So there is no longer a need for additional margins (found by trial and error) to compensate for that problem. The "Distance" property is now obsolete.

Side note: I do still keep a fixed one-pixel margin in between glyphs in the font texture because it prevents the edges of neighboring glyphs from being "bleeding over" while blitting individual glyphs from the font texture at render time. This is a completely separate issue, however; it has to do with the way the GPU applies UV coordinates to extract portions of a texture while filtering is also being applied.


2. While standard "Not Defined" and is useful for developers I believe that spaces are more user friendly and clear for them. Best variant is making that "Not Defined" taken from font's description, with space or square by default and possibility to use any other character.

My patch already uses the "Not Defined" character defined in the font itself as you recommend. In most cases it's a square or rectangle but some fonts use their own custom design. I think users are used to seeing this as a substitution glyph because it is standard behavior everywhere. However if you feel differently it shouldn't be hard to add another property that allows the application developer to specify a different character to use instead. Please let me know if you would like me to do that and I'll include it in my patch.

Altren

13-01-2012 08:27:54


2. While standard "Not Defined" and is useful for developers I believe that spaces are more user friendly and clear for them. Best variant is making that "Not Defined" taken from font's description, with space or square by default and possibility to use any other character.

My patch already uses the "Not Defined" character defined in the font itself as you recommend. In most cases it's a square or rectangle but some fonts use their own custom design. I think users are used to seeing this as a substitution glyph because it is standard behavior everywhere. However if you feel differently it shouldn't be hard to add another property that allows the application developer to specify a different character to use instead. Please let me know if you would like me to do that and I'll include it in my patch.
I guess I described it a bit wrong, by "font's description" I meant MyGUI's font's description, i.e. ResourceTrueTypeFont. And yeah, it would be great to see that in your patches as well. You can do that as separate patch though, since we want to see first patch as soon as possible :)

Spire

14-01-2012 01:58:35

My patch already uses the "Not Defined" character defined in the font itself as you recommend. In most cases it's a square or rectangle but some fonts use their own custom design. I think users are used to seeing this as a substitution glyph because it is standard behavior everywhere. However if you feel differently it shouldn't be hard to add another property that allows the application developer to specify a different character to use instead. Please let me know if you would like me to do that and I'll include it in my patch.
I guess I described it a bit wrong, by "font's description" I meant MyGUI's font's description, i.e. ResourceTrueTypeFont. And yeah, it would be great to see that in your patches as well. You can do that as separate patch though, since we want to see first patch as soon as possible :)

Ah, I see. Well, let me know if you'd like me to add that in a future patch.

In the meantime, I've just submitted my main patch here.

I've documented my code pretty thoroughly, so I hope it isn't too difficult to follow. If you decide to accept my patch after reviewing it, please let me know if you'd like me to make any changes.

The only thing in my patch that I'm a little unsure about is the location of two helper function templates I've written, setMin() and setMax(). I've put them in MyGUI_Macros.h for now, but I suspect there's a better place for them -- perhaps a new file.

Looking forward to your feedback.

Altren

16-01-2012 22:35:54

[Reposting this message because I thought I had posted it a few days ago, but it appears not to have gone through.]It wasn't shown because you had not enough forum posts to have links in them (wasn't shown until forum moderator (i.e. me) approved it and unfortunately I noticed it only today).

Implements subpixel positioning. This significantly improves the overall apperance and "color" of text, especially at small sizes and in even more so in pathological cases where a widget has overridden a font's height by setting the "FontHeight" property to a low value. For example, in cases where spacing in between glyphs is supposed to be around 1.5 pixels, the code would previously sometimes use 1 pixel and sometimes use 2, resulting in very uneven spacing. This problem no longer occurs at all, as some portions of horizontal text layout are now performed internally using floating point.

Note that the use of floating point for some calculations does not appreciably hinder application performance. In fact, extensive benchmarking has shown that the overall performance of the font layout and rendering code is still much higher than before.
The point of using int's was to have same glyphs rendered in the same way. When same glyph have position 10 in one place and 10.5 in another result is that it looks slightly different.

The only thing in my patch that I'm a little unsure about is the location of two helper function templates I've written, setMin() and setMax(). I've put them in MyGUI_Macros.h for now, but I suspect there's a better place for them -- perhaps a new file.We decided, that it is better to use
value = std::max(value, value1);and not have this functions at all. Code is clear enough and compiler will optimize it in same code anyway.

We are analysing whole patch and it might take few days, but in general everything looks very good and we are glad, that you sent this patch. Thank you.

Our current plan is to change few minor things like removing setMin/setMax, test some stuff and then we will probably commit the changes into svn. We can also give you write svn access to simplify adding further related changes, if you need them.

Altren

16-01-2012 22:45:20

Few things to think about. More changes, that need to be done are:
  1. Custom "Not Defined" character option that we have already discussed;[/*:m]
  2. Possibility to use bearing in manual fonts (should be easy to implement);[/*:m]
  3. Modify "FontViewer" tool to save those bearings in manual font.[/*:m][/list:o]

Altren

16-01-2012 22:49:45

The point of using int's was to have same glyphs rendered in the same way. When same glyph have position 10 in one place and 10.5 in another result is that it looks slightly different.So far I haven't noticed any.

And one more thing - in some cases texture size looks odd, for example I got 64x256 texture size for default font with size 12. I expected more squared textures, i.e. 128 x 128.
Looks like there is bug in math, since with size 13 I got 128 x 128 texture.

Spire

17-01-2012 00:44:06

We are analysing whole patch and it might take few days, but in general everything looks very good and we are glad, that you sent this patch. Thank you.
That's great to hear! I'm happy that my efforts in cleaning it up for release are not going to go to waste and that others will be able to benefit from it.


The only thing in my patch that I'm a little unsure about is the location of two helper function templates I've written, setMin() and setMax(). I've put them in MyGUI_Macros.h for now, but I suspect there's a better place for them -- perhaps a new file.
We decided, that it is better to use
value = std::max(value, value1);and not have this functions at all. Code is clear enough and compiler will optimize it in same code anyway.

For what it's worth, I tested this using Visual Studio 2010 by inspecting the generated assembly code, and unfortunately it turns out that the compiler is unable to optimize the assignment away when it isn't necessary (regardless of the optimization settings). I'm not sure how important this is to you, but the setMin()/setMax() version of the code is measurably faster than the naïve std::min()/std::max() version. Because this code tends to get called inside tight loops where performance matters, I'd prefer to keep my helper functions in the patch if you don't mind too much.

Our current plan is to change few minor things like removing setMin/setMax, test some stuff and then we will probably commit the changes into svn. We can also give you write svn access to simplify adding further related changes, if you need them.
Thank you very much offering me write access to the repository -- that will definitely make things a lot easier. I'd like to commit under the user name "Spire" if possible. (Or it might make better sense to use my SourceForge user name, "spire42".)

If it's not too much to ask, since I'm going to have write access to the repository, I'd like to be the one to commit my big patch (after incorporating whatever changes you need, of course).

Few things to think about. More changes, that need to be done are:
  1. Custom "Not Defined" character option that we have already discussed;[/*:m]
  2. Possibility to use bearing in manual fonts (should be easy to implement);[/*:m]
  3. Modify "FontViewer" tool to save those bearings in manual font.[/*:m][/list:o]

I'd be happy to implement these changes in future patches. I'll start working on them once the main patch is committed, so that I don't have to manage so much uncommitted stuff at once.

You might be amused to hear that I was also going to suggest adding support for specifying bearing and advance values in manual fonts! Right now, character combinations like "ij" tend to look pretty ugly.

And one more thing - in some cases texture size looks odd, for example I got 64x256 texture size for default font with size 12. I expected more squared textures, i.e. 128 x 128.
Looks like there is bug in math, since with size 13 I got 128 x 128 texture.

That's not actually a bug but rather a rare edge case. Here's why it happens:

My algorithm first performs an estimate of the required texture size. During the estimation process, it attempts to make the texture square, but if this isn't possible, it errs on the side of making it tall.

The reason it chooses to make it tall (instead of wide) is that during the second calculation pass, the texture height is very likely to decrease due to height packing. In many cases this actually causes the final texture to become perfectly square again. However, in some rare cases with certain fonts and at certain sizes, the texture height instead increases during this second pass -- and in even rarer cases, this increase manages to push the height just over the threshold to the next power of two.

In my testing with dozens of different fonts and at many different sizes, I found that in the vast majority of cases the texture size ended up being either N×N or N×2N. Only very rarely did a texture of size N×4N occur. Looks like you got extremely unlucky!

It's possible to write special handling to detect this case and redo the second pass of layout calculations to correct for it, but I'm not sure it would be worth the trouble (since it's harmless). What do you think?

Altren

17-01-2012 20:32:42

I gave you write svn access, just use same svn repository and youre sourceforge login/pass. Here's few changes, that you should make in your current patch:
  1. Remove MYGUI_FORCEINLINE from all places.[/*:m]
  2. Remove declarations formatting (as in ResourceTrueTypeFont.h in variables declarations)- we don't use that, because it require additional time whenever you change code (sometimes need to change all other lines as well) and also not all developers use monospace fonts, so it might be off.[/*:m]
  3. Either move setMin/setMax functions into files where it is used or replace with std::min/max.[/*:m][/list:o]

    I'd be happy to implement these changes in future patches. I'll start working on them once the main patch is committedYou are welcome.
    It's possible to write special handling to detect this case and redo the second pass of layout calculations to correct for it, but I'm not sure it would be worth the trouble (since it's harmless). What do you think?Leave it as it is not. Since it is expected and known behaviour I think it is ok.

simed

17-01-2012 20:42:20

Very cool spire - as a fellow MyGUI user thanks for taking the effort to share your local improvements.

You described in detail how your improvements are technically better - but could you summarise what this will mean for someone using MyGUI... do we have to do anything different or will it just mean fonts look nicer and are more performant?

Altren

17-01-2012 21:25:04

do we have to do anything different or will it just mean fonts look nicer and are more performant?There are no changes in use cases at all, so you don't need to do any changes in user code to get new behaviour: fonts will look a bit better and will generate smaller textures in runtime, i.e. you can use more characters in your fonts definition. Also I'm sure that this change is very important for Chinese fonts, since there are always much more characters in it.

Spire

18-01-2012 23:35:58

You described in detail how your improvements are technically better - but could you summarise what this will mean for someone using MyGUI... do we have to do anything different or will it just mean fonts look nicer and are more performant?
As Altren has explained, most of the changes are under the hood and require no changes on the part of MyGUI users -- other than perhaps some adjustments to layouts, which may have shifted around a bit due to the corrections I've made to the font metrics calculations.

There is one new thing, however, that MyGUI users can directly benefit from: support for simplified font definitions.

Take, for example, the "DejaVu Sans" font that comes with MyGUI. Let's say you want to use this font at 12 pt (96 PPI) and that you want to include all of the characters that the font has to offer while excluding all unsupported characters.

Here's how you previously would have had to do it:


<Resource type="ResourceTrueTypeFont" name="DejaVuSansFont">
<Property key="Source" value="DejaVuSans.ttf"/>
<Property key="Size" value="12"/>
<Property key="Resolution" value="96"/>
<Property key="Antialias" value="false"/>
<Property key="SpaceWidth" value="5"/>
<Property key="TabWidth" value="40"/>
<Property key="CursorWidth" value="2"/>
<Property key="Distance" value="6"/>
<Property key="OffsetHeight" value="0"/>
<Codes>
<Code range="0 65535"/>
<Code hide="32"/>
<Code hide="127 159"/>
<Code hide="746 747"/>
<Code hide="751 754"/>
<Code hide="756 758"/>
<Code hide="760 767"/>
<Code hide="848"/>
<Code hide="852 854"/>
<Code hide="857 859"/>
<Code hide="867 879"/>
<Code hide="882 883"/>
<Code hide="886 889"/>
<Code hide="895 899"/>
<Code hide="907"/>
<Code hide="909"/>
<Code hide="930"/>
<Code hide="975"/>
<Code hide="1159"/>
<Code hide="1300 1305"/>
<Code hide="1310 1311"/>
<Code hide="1316 1328"/>
<Code hide="1367 1368"/>
<Code hide="1376"/>
<Code hide="1416"/>
<Code hide="1419 1455"/>
<Code hide="1476 1477"/>
<Code hide="1480 1487"/>
<Code hide="1515 1519"/>
<Code hide="1525 1541"/>
<Code hide="1544"/>
<Code hide="1547"/>
<Code hide="1549 1556"/>
<Code hide="1558 1562"/>
<Code hide="1564 1566"/>
<Code hide="1568"/>
<Code hide="1595 1599"/>
<Code hide="1622 1625"/>
<Code hide="1627 1631"/>
<Code hide="1648 1651"/>
<Code hide="1653 1656"/>
<Code hide="1672 1680"/>
<Code hide="1683 1684"/>
<Code hide="1686 1687"/>
<Code hide="1689 1696"/>
<Code hide="1698 1699"/>
<Code hide="1701"/>
<Code hide="1703 1704"/>
<Code hide="1706 1710"/>
<Code hide="1712 1716"/>
<Code hide="1718 1721"/>
<Code hide="1723 1726"/>
<Code hide="1728 1733"/>
<Code hide="1735 1739"/>
<Code hide="1741"/>
<Code hide="1743 1748"/>
<Code hide="1750 1775"/>
<Code hide="1786 1983"/>
<Code hide="2024 2026"/>
<Code hide="2038 2039"/>
<Code hide="2043 3646"/>
<Code hide="3648 3712"/>
<Code hide="3715"/>
<Code hide="3717 3718"/>
<Code hide="3721"/>
<Code hide="3723 3724"/>
<Code hide="3726 3731"/>
<Code hide="3736"/>
<Code hide="3744"/>
<Code hide="3748"/>
<Code hide="3750"/>
<Code hide="3752 3753"/>
<Code hide="3756"/>
<Code hide="3770"/>
<Code hide="3774 3775"/>
<Code hide="3781"/>
<Code hide="3783"/>
<Code hide="3790 3791"/>
<Code hide="3802 3803"/>
<Code hide="3806 4255"/>
<Code hide="4294 4303"/>
<Code hide="4349 5120"/>
<Code hide="5128"/>
<Code hide="5148"/>
<Code hide="5174"/>
<Code hide="5195"/>
<Code hide="5203"/>
<Code hide="5310 5311"/>
<Code hide="5355"/>
<Code hide="5384 5391"/>
<Code hide="5439"/>
<Code hide="5457"/>
<Code hide="5483 5491"/>
<Code hide="5510 5513"/>
<Code hide="5527 5535"/>
<Code hide="5552 5597"/>
<Code hide="5599 5600"/>
<Code hide="5602 5701"/>
<Code hide="5704 5741"/>
<Code hide="5751 5759"/>
<Code hide="5789 7423"/>
<Code hide="7445"/>
<Code hide="7460 7461"/>
<Code hide="7471"/>
<Code hide="7516"/>
<Code hide="7531 7542"/>
<Code hide="7545 7546"/>
<Code hide="7548 7556"/>
<Code hide="7558 7578"/>
<Code hide="7616 7619"/>
<Code hide="7626 7679"/>
<Code hide="7836 7838"/>
<Code hide="7930 7935"/>
<Code hide="7958 7959"/>
<Code hide="7966 7967"/>
<Code hide="8006 8007"/>
<Code hide="8014 8015"/>
<Code hide="8024"/>
<Code hide="8026"/>
<Code hide="8028"/>
<Code hide="8030"/>
<Code hide="8062 8063"/>
<Code hide="8117"/>
<Code hide="8133"/>
<Code hide="8148 8149"/>
<Code hide="8156"/>
<Code hide="8176 8177"/>
<Code hide="8181"/>
<Code hide="8191"/>
<Code hide="8232 8233"/>
<Code hide="8293 8297"/>
<Code hide="8306 8307"/>
<Code hide="8335"/>
<Code hide="8341 8351"/>
<Code hide="8374 8399"/>
<Code hide="8402 8405"/>
<Code hide="8408 8410"/>
<Code hide="8413 8416"/>
<Code hide="8418 8447"/>
<Code hide="8458"/>
<Code hide="8522"/>
<Code hide="8524 8525"/>
<Code hide="8527 8530"/>
<Code hide="8581 8591"/>
<Code hide="8880 8881"/>
<Code hide="8903"/>
<Code hide="8912 8917"/>
<Code hide="8978 8983"/>
<Code hide="8986 8987"/>
<Code hide="8994 8995"/>
<Code hide="9001 9002"/>
<Code hide="9005 9074"/>
<Code hide="9078 9081"/>
<Code hide="9083 9084"/>
<Code hide="9086 9094"/>
<Code hide="9096 9107"/>
<Code hide="9109 9114"/>
<Code hide="9135 9165"/>
<Code hide="9168 9186"/>
<Code hide="9188"/>
<Code hide="9190 9249"/>
<Code hide="9252 9311"/>
<Code hide="9322 9471"/>
<Code hide="9885 9887"/>
<Code hide="9907 9984"/>
<Code hide="9989"/>
<Code hide="9994 9995"/>
<Code hide="10024"/>
<Code hide="10060"/>
<Code hide="10062"/>
<Code hide="10067 10069"/>
<Code hide="10071"/>
<Code hide="10079 10080"/>
<Code hide="10133 10135"/>
<Code hide="10160"/>
<Code hide="10175 10180"/>
<Code hide="10183 10207"/>
<Code hide="10209 10213"/>
<Code hide="10220 10223"/>
<Code hide="10496 10501"/>
<Code hide="10504 10505"/>
<Code hide="10508 10559"/>
<Code hide="10562 10626"/>
<Code hide="10629 10701"/>
<Code hide="10710 10730"/>
<Code hide="10732 10745"/>
<Code hide="10748 10751"/>
<Code hide="10755 10763"/>
<Code hide="10781 10798"/>
<Code hide="10800 10876"/>
<Code hide="10913 10925"/>
<Code hide="10939 11000"/>
<Code hide="11003 11007"/>
<Code hide="11035 11039"/>
<Code hide="11044 11359"/>
<Code hide="11376"/>
<Code hide="11384"/>
<Code hide="11386"/>
<Code hide="11390 11567"/>
<Code hide="11622 11630"/>
<Code hide="11632 11799"/>
<Code hide="11801 11821"/>
<Code hide="11823 19903"/>
<Code hide="19968 42563"/>
<Code hide="42568 42571"/>
<Code hide="42574 42575"/>
<Code hide="42578 42579"/>
<Code hide="42584 42593"/>
<Code hide="42600 42633"/>
<Code hide="42638 42643"/>
<Code hide="42646 42769"/>
<Code hide="42775 42789"/>
<Code hide="42796 42799"/>
<Code hide="42816 42821"/>
<Code hide="42828 42829"/>
<Code hide="42832 42879"/>
<Code hide="42882 42890"/>
<Code hide="42893 43002"/>
<Code hide="43008 61439"/>
<Code hide="61442 63172"/>
<Code hide="63174 64255"/>
<Code hide="64263 64274"/>
<Code hide="64280 64284"/>
<Code hide="64311"/>
<Code hide="64317"/>
<Code hide="64319"/>
<Code hide="64322"/>
<Code hide="64325"/>
<Code hide="64336 64337"/>
<Code hide="64386 64393"/>
<Code hide="64406 64413"/>
<Code hide="64416 64472"/>
<Code hide="64475 64487"/>
<Code hide="64490 64507"/>
<Code hide="64512 65023"/>
<Code hide="65040 65055"/>
<Code hide="65060 65135"/>
<Code hide="65141"/>
<Code hide="65277 65278"/>
<Code hide="65280 65528"/>
<Code hide="65534 65535"/>
</Codes>
</Resource>

And here's how you can it now:


<Resource type="ResourceTrueTypeFont" name="DejaVuSansFont">
<Property key="Source" value="DejaVuSans.ttf"/>
<Property key="Size" value="12"/>
</Resource>

I think that's a win.

jsding

31-01-2012 04:17:40

I have updated to this version, the font texture 2048 * 2048 reduced to 2048 * 1024 (great improvements). But the whitespace rendered as "!", what's the problem?

Thanks for your help

Altren

31-01-2012 08:32:29

Could you post your font definition?

jsding

31-01-2012 09:36:43

Simply

<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Resource" version="1.1">
<Resource type="ResourceTrueTypeFont" name="simhei.17">
<Property key="Source" value="simhei.ttf"/>
<Property key="Size" value="16"/>
</Resource>
</MyGUI>


the simhei.ttf is 2.5m chinese font file.

Could you post your font definition?

Spire

31-01-2012 10:30:20

Could you please verify that you're using the latest revision of MyGUI (r4359)?

If you are, I'll try to take a look at this in the next couple of days.

jsding

31-01-2012 10:52:07

Thanks, I confirm i am using the latest version (r4359).

Could you please verify that you're using the latest revision of MyGUI (r4359)?

If you are, I'll try to take a look at this in the next couple of days.

Spire

31-01-2012 20:06:31

I can't reproduce the problem.

I tried using your font definition in conjunction with the simhei.ttf that comes with Windows 7 (version 5.01, 9,751,960 bytes). Not only are the space characters being rendered correctly for me, my texture size is very different from yours (4,096×4,096 instead of 2048×1024).

There must be something different on your end that is causing MyGUI to behave differently. Did you ever build MyGUI after manually applying my patch file (before I committed it)? If you did, you need to revert your copy of MyGUI to a clean checkout and rebuild it.

Also, could you post all of the lines of your MyGUI.log file that mention ResourceTrueTypeFont?

jsding

01-02-2012 07:05:15

I am not really using the "simhei.ttf", I am using a ttf which reduced some uncommon characters. Is there a really "Space" character in the ttf file?

Thanks for your help

Spire

01-02-2012 07:11:01

There is definitely a "Space" character defined in the original simhei.ttf. Whoever modified the font for you must have accidentally removed it.

I'm glad this mystery is solved.

jsding

02-02-2012 01:13:45

I've checked the ttf file, the space character accidentally removed! :shock: Thanks for your help

There is definitely a "Space" character defined in the original simhei.ttf. Whoever modified the font for you must have accidentally removed it.

I'm glad this mystery is solved.