Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic font support #6324

Open
geniuszxy opened this issue May 23, 2018 · 74 comments

Comments

Projects
None yet
@geniuszxy
Copy link

commented May 23, 2018

I mean, at runtime,
load a font file, read some glyhps and render them into a texture.
then use it like a normal SpriteFont.
This feature is very important for asian users. because we use about 2000 common characters and a large amount of rare characters.
Put then into a xnb file is almost impossible (takes very long time to build and gets very large xnb file).
I have searched on the internet but no usable solution yet.

@tomspilman tomspilman added this to the 5.0 milestone May 23, 2018

@MichaelDePiazzi

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

I recently implemented something like this in my game, Final Days. What I did was a bit hacky, but it works. Unfortunately, I can't submit what I've done to MonoGame as it's very much a bespoke solution for my game.

I did a fair bit of research into this to try and find a good solution. But one of my requirements was to have font fallback (i.e. if the font you're using doesn't have the glyph you need, then it falls back to another similar font which does have that glyph). Unfortunately, this is easier said than done. The most practical solution I came up with was to use Windows GDI+ to render the glyphs. But this has it's own issues and I definitely came across a few quirks and inconsistencies. It obviously also only works with Windows.

But once the glyph rendering is taken care of, the rest was fairly straightforward (although it was a bit of work). Basically whenever I needed to display missing glyphs, I'd render those glyphs in the background and update the SpriteFont to include them.

If you'd like more details on how I did this, then I'd be happy to share them and try answer any questions.

@tomspilman

This comment has been minimized.

Copy link
Member

commented May 31, 2018

It obviously also only works with Windows.

That is the biggest issue. We need an portable font rasterizer we can call at runtime. Platform specific ones will not work as they all produce different results... meaning your fonts look different on different platforms. It has to be non-GPL so we can use it on consoles as well.

Once we have a solution for that the rest is all pretty easy.

@MichaelDePiazzi

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

That is the biggest issue. We need an portable font rasterizer we can call at runtime. Platform specific ones will not work as they all produce different results... meaning your fonts look different on different platforms. It has to be non-GPL so we can use it on consoles as well.

All I came across was Cairo. There's a C# wrapper for it called CairoSharp. I don't know if it would be suitable for MonoGame though. The licence is LGPL, but apparently it can also be used under the Mozilla Public Licence (MPL). Not sure if that helps? CairoSharp seems to only have LGPL though.

@cra0zy

This comment has been minimized.

Copy link
Member

commented May 31, 2018

Cairo is licensed under LGPL or MPL, CairoSharp on the other hand is LGPL only. I don't think its a good idea to use a native library for this purpose, its way better if something like Typography could fit our purposes.

On a side note, I'm maintaining a fork of gtk-sharp here, which also includes CairoSharp which uses delegate invoking of functions instead of dllmap so it should be better than that fork, tho it probably misses a few functions compared to it.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

Typography looks super cool for being a pure C# solution. Cairo does more than just font rasterizing, and I would be more favorable to a lib that does just what we need here.

I would be pretty curious about Typography performances.

There's a desperate need for a runtime glyph rasterizer in MonoGame. Localizing is such a pain (we ended up creating bitmap font hacks that use only the useful glyphs, but it can get pretty quickly unmanageable with higher word count).

I hear a lot about bmfont from other gamedevs: http://www.angelcode.com/products/bmfont/
I haven't looked into it, but it's open source and maybe the rasterizer can be used separately.

stb_truetype is also worth mentioning but it is known to be super slow.

Also, +100 to anything supporting emojis.

@MichaelDePiazzi

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

I did come across Typography in the past and it definitely looked promising. But it didn't seem to do font fallback, so I didn't end up going further with it.

I only brought up Cairo because it was the only cross-platform open source library I came across which seemed to handle font fallback.

But font fallback was just something I specifically needed for my requirements. I'm not sure if it would be required for MonoGame as well. But it was definitely very handy not having to worry about glyphs that were missing from the font you were using.

If you don't need font fallback though, it makes things a LOT easier and there are a few options about (e.g. SharpFont which MonoGame already uses in the Content Pipeline).

@MichaelDePiazzi

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

Also, +100 to anything supporting emojis.

Emoji support is tricky as SpriteFont only supports UCS-2 characters (i.e. Unicode U+0000 to U+FFFF), and emojis are outside of this range. I did experiment with a workaround which remapped Unicode characters outside of this range into the private use area (U+E000 to U+F8FF). It worked pretty well, but unfortunately the GDI+ renderer I ended up using only supported UCS-2 as well 😒

@tomspilman

This comment has been minimized.

Copy link
Member

commented May 31, 2018

But font fallback was just something I specifically needed for my requirements. I'm not sure if it would be required for MonoGame as well. But it was definitely very handy not having to worry about glyphs that were missing from the font you were using.

We could do font fallback by specifying multiple fonts like you do in CSS. Then worst case we automatically pick a system font if all else fails.

@tomspilman

This comment has been minimized.

Copy link
Member

commented May 31, 2018

e.g. SharpFont which MonoGame already uses in the Content Pipeline).

We could use SharpFont/FreeType at runtime, but i would love to try some fully managed libraries first.
And if we find a good runtime font solution we like we would convert the pipeline to use it for offline rendering as well.

@cra0zy

This comment has been minimized.

Copy link
Member

commented May 31, 2018

@tomspilman As I mentioned above, https://github.com/LayoutFarm/Typography might be a good solution.

@MichaelDePiazzi

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

We could do font fallback by specifying multiple fonts like you do in CSS. Then worst case we automatically pick a system font if all else fails.

For sure. This was something I was seriously considering as well, but shied away from because it meant including multiple font files. But ultimately this solution does give you more control over how glyphs are rendered. And it may also be the only choice on some platforms which may not even provide a font fallback mechanism.

@Jjagg

This comment has been minimized.

Copy link
Contributor

commented May 31, 2018

As another managed alternative, there's SixLabors/Fonts.

@cra0zy

This comment has been minimized.

Copy link
Member

commented May 31, 2018

As another managed alternative, there's SixLabors/Fonts.

Nice!

@alkalinethunder

This comment has been minimized.

Copy link

commented May 31, 2018

Someone in this thread mentioned Cairo for run-time font rendering. I can vouch for it. I used to use it in my game back when user-interface skinning was a thing and we needed user-selected fonts that could be rendered at runtime. If you write the actual rendering code in C++ - i.e, create a function for measuring text and one for rendering to a bitmap in memory - and P/invoke into that middle-man C++ library, it's very fast.

The issues are that you have to compile that C++ middle-man for all the different platforms you need. And you need to make sure that Cairo (and Pango which we also used) are supported on those platforms.

But if you jump over that hurdle, dynamic SpriteFont loading directly from TrueType font files or even font families installed to the system becomes real easy (The latter at least, not entirely sure about the former).

@stromkos

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

I have a working Android version of font replacement, redraw fonts within current bounds, to replace standard chars with color emojis. It adds about 5 seconds to the load time. I am working on a generalized version of this, but you can not mix color fonts with regular fonts. So far this solution will only work for Android and Windows platforms. If someone is willing to work on the ios/other platforms specific code, we could develop a standardized API for runtime fonts.

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

Another solution would be to use StbSharp/StbTrueType.
Right now, it's MonoGame Sample demonstrates how to dynamically create a SpriteFont: https://github.com/rds1983/StbSharp/blob/c3220a9dae71fd3491d7b5bf8bfe0d1f82f08ea8/Samples/StbSharp.MonoGame.Test/Game1.cs#L44
image

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

That's very interesting! StbSharp being a pure C# library without any native dependencies, it's a very good candidate for all platforms.

Your example is quite cool to bake fonts at runtime given a character set. I might very well switch to StbSharp for our own projects.

I have been playing around with Typography, SixLabors/Font, and Cairo lately, and they all are cumbersome to use and with other native dependencies (and most of them use System.Drawing, which is a pain cross-platform wise).

So far, I'm all in for StbSharp.

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

It has downside - the font baker API(which is wrapper over stb_truetype) is very simple: https://github.com/rds1983/StbSharp/blob/master/StbSharp/FontBaker.cs
I've made it just to check whether the thing works.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

I'm going to give it a try, checking performance and font compatibility.

@cra0zy

This comment has been minimized.

Copy link
Member

commented Nov 3, 2018

There is one more downside, its unusable on the web port of MonoGame.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

Because of reflection and/or unsafe code?

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

btw, there's another stb_truetype port to C# made by @KonajuGames: https://github.com/KonajuGames/TrueTypeSharp/tree/master/TrueTypeSharp
I haven't reviewed it throughfully. But from the glance it doesnt have unsafe code.

@cra0zy

This comment has been minimized.

Copy link
Member

commented Nov 3, 2018

Reflection works, unsafe code does not.

On a related note I finally managed to fix up content manager for web, its now as fast as other platforms.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Nov 3, 2018

@KonajuGames 's port / the original TrueTypeSharp doesn't have unsafe code, but is missing 4 years of improvements. I wonder if an updated version would be too much work.

It would be cool to have this working on the web and on consoles.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Nov 6, 2018

I've been playing around with the Stb.

Konaju's port has some issues and the original TrueTypeSharp is outdated (and using a less clean rasterizer). Bringing it on par with the latest Stb_truetype sounds like a lot of work since parts of the library went over redesign / refactoring.

I started to try removing the unsafe parts from StbSharp, which sounds very doable but is a lot of work to make sure that everything works as expected.

@rds1983 Do you think it would be possible to add an option to Sichem to produce safe code? The FakePtr from TrueTypeSharp looks like a solution (and is of course very garbage prone, unless it would manage its own memory pool).

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Nov 6, 2018

@mrhelmut

Do you think it would be possible to add an option to Sichem to produce safe code? The FakePtr from TrueTypeSharp looks like a solution (and is of course very garbage prone, unless it would manage its own memory pool).

That's awesome idea!
I'll definitely give it a try.

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Nov 6, 2018

I've added the option to Sichem to produce safe code and tested it out on stb_truetype. And it worked!
New safe version of StbSharp is here: https://github.com/rds1983/StbSharp/tree/master/StbSharpSafe
I've also added new MonoGame sample that works with StbSharpSafe: https://github.com/rds1983/StbSharp/tree/master/Samples/StbSharpSafe.MonoGame.Test

image

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Jan 17, 2019

I've made a library that allows dynamic creation of SpriteFont: https://github.com/rds1983/SpriteFontPlus
@geniuszxy

@willmotil

This comment has been minimized.

Copy link
Contributor

commented Jan 21, 2019

The StbSharp dynamic font above i think is made by the same guy as the thing we use now not 100% on that.

Anyways. I added unicode support to the above the project and it just uses a renderer i tossed together to test it.

https://drive.google.com/open?id=19eVSczTid9oqOLjK3LyAyAPn7wsur9mn

Drawstring getting unicode support amounts to a assignment to a int and a single if check the vast majority of the entire loop cycle, which is a negligible performance hit. Basically this is very little if any penalty.

        for (int i = 0; i < text.Length; i++)
        {
            char cs = text[i];
            int charval = cs;  // (1)
            if (char.IsHighSurrogate(cs))   // (2)  be nice to implement this in place we could check manually for the hex code range.
            {
                // essentially we get to skip a character next pass so this is extremely minor as well.
                charval = char.ConvertToUtf32(cs, text[i + 1]); 
                i++;
            }
            
            // there is really no other downside after the above performance wise.
            if (charval == '\r')
                continue;
            if (charval == '\n')
            {

Ok so jjagg has a wip for unicode support which is like as far as i can tell is just about finished.
So i just wanted to point out that it appears getting full unicode support in monogame is approaching imminently.
This issue goes back a long way and the original preliminary discussion is here #4805

I suppose it would be nice to get both at once dynamic font support and proper unicode capability.
This route seems to do that.

It also just from initial tests seems to get rid of the horrible looking alpha pixels and bad aliasing (that occurs differently at different point sizes) that the current font loader seems to generate into the texture.
#5242 #5272 #6614 all still open and more.

It looks amazingly good under spritebatch i don't have to tinker with settings either to try to clear it up.
Not shown in the above image but it is when you run the project.

The above image is of course just a quick hacked in font rendering class right out of a test i was working on for something else at the moment. Its not a very good renderer but it shows the results of StbSharp with unicode support.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 21, 2019

I'd like to note that StbSharp is very useful (thanks @rds1983 !), but doesn't support hinting, which makes smaller fonts very blurry compared to what freetype is currently outputing through the content pipeline.

This would mean that dynamic fonts would render differently from standard SpriteFont. We'll have to keep that in mind when moving forward.

@willmotil

This comment has been minimized.

Copy link
Contributor

commented Jan 21, 2019

Freetype's output is quite frankly horrible even on small sizes...
http://community.monogame.net/t/spritefont-rendering-cant-seem-to-disable-smoothing/11225/9

Look at the J specifically. Unseen really here but the zero was turned into a e

stb has some problems so far but freetype has been in use for a long while and it still hasn't been fixable.

StbSharp small text 15 pixel height which is like an 9 point spritefont. Scaled way up. same fonts.
I can make these opaque as the pixels come in but this is how it comes in on its own.
zoomed01

stbsharp20height

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 21, 2019

It depends on the font and if it has hinting. A font with good hinting enabled (such as this one: https://github.com/SolidZORO/zpix-pixel-font) will be super crisp with freetype and blurry with StbSharp at low size.

Font without hinting will look bad anyway.

Regarding http://community.monogame.net/t/spritefont-rendering-cant-seem-to-disable-smoothing/11225/9, we could add a parameter to the content processor to tell freetype to not use anti-aliasing.

Also note that anti-aliasing is different from hinting. Hinting are properties defined by the font to give hints to the renderer regarding how some subpixels should be handled at specific size. If the renderer doesn't support hinting, most subpixels are going to be interpolated (and most likely wrong).

@willmotil

This comment has been minimized.

Copy link
Contributor

commented Jan 21, 2019

we could add a parameter to the content processor to tell freetype to not use anti-aliasing.

That would probably be a good thing.
A option in the pipeline tool would be better but the aliasing if that is really what that's from is just terrible for freetype i don't think anyone would keep it on for long if they had a choice.

Well it doesn't matter to me which is used if we can get rid of that alaising.
I think i got off track a bit though can freetype dynamically load the fonts.

@Jjagg

This comment has been minimized.

Copy link
Contributor

commented Jan 22, 2019

@mrhelmut FreeType also has an auto-hinter that heuristically hints fonts without the font file containing hinting information.

@willmotil It's unfair to scale up a glyph and then say it's badly rendered because it's not close to what you'd expect for the character. It's rendered specifically to look good when unscaled.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 22, 2019

Anti-aliasing should definitely be controlled, but that's probably worth opening another issue than this one.

On my end, I care about big AND small fonts accuracy. If we go with StbSharp, we should keep in mind (i.e. document) that it doesn't support hinting and ultimately add hinting support to the original stb_truetype so that it can be ported to StbSharp.

Speaking of anti-aliasing, a dynamic font should also support to toggle it.

@willmotil

This comment has been minimized.

Copy link
Contributor

commented Jan 22, 2019

@willmotil It's unfair to scale up a glyph and then say it's badly rendered because it's not close to what you'd expect for the character. It's rendered specifically to look good when unscaled.

Yes but it doesn't render correctly un-scaled for many fonts as well.

The scaling up in the image previously was just done to zoom in to what is going on as point clamp was on. In order to show that some pixels are in fact there, but just so aliased that they are invisible.
Below i remade a better example which is not zoomed in at all.

It seems ridiculous that im about to argue that our current font rendering is anything but reliable.
I thought this was a given and obvious fact but here goes, this will get off topic for a minute.
.....

Edited to demonstrate with a good example.

.
.

Just to be clear im not arguing for or against FreeType i never was.
Im arguing that it does in fact have problems.
Im arguing that it doesn't always render fonts at small sizes well or even larger sizes for some.

Hinted fonts may render well small but un-hinted ones get the opposite effect.
They in many cases actually rendered worse then they should be, to the point of actually changing characters which im about to demonstrate in images below

For example this unhinted font is made far worse with monogame then it is with this StbSharp.
So it does seem there is a trade off you get really good small hinted fonts.
but far far worse un-hinted ones over a wider point size.
Some to the point of being unusable or unreliable.

Example Current MonoGame Implementation.
Font used unifont -
Its a un-hinted extremely simple small basic font with 65 k characters covering the first half of the unicode spectrum 0x0000 to 0xFFFF holding glyphs for the entire char range of what SpriteBatch currently supports.

unifont point size 12 << flawless.

unifontpointsize12

unifont point size 14 <<< !!! look at the zero. !!!

unifontpointsize14

How would you define the behavior of monogame here if you just started using it ?
How would you define the condition of this font now ?

Maybe the answer is that you just use specific point sizes ?
This turns out to be wrong as well.

How do i know what the right point size is of other fonts ?
Answer.... i don't.
Logic ... Just look for them ?
A terrible solution and also...
Wrong again.
For some fonts there simply wasn't one as far as i could find that didn't create artifacts this one just happens to work at point size 12 and 24 at other scales different letters get roached.

Scaling up via sprite batch doesn't change anything as this is already directly messed up from the importing of the font into spritefont.

So as it stands in reality if we are to say freetype is the superior answer.
We must acknowledge that it also wrecks un-hinted fonts.
I don't think that is acceptable long term.

This is something that manifests i think for most users as a head scratcher or something they can't put there finger on, rather then a understood problem. For me it was, until i fully realized what was going on at the time of that post which is why i could make and repost the artifact from scratch as i did here.

Just to add in... In almost every other way freetype seems superior at least with hinted fonts.
Except the above and that is a downside that is serious enough to make many fonts practically unusable or really randomly bad. Versus, just not look as good using something else. Especially as many free fonts are not hinted.

If that could be fixed for freetype it would be a huge relief and definitely superior at that point.

Then conversely if hinting could be added to stb_truetype it would probably be comparable quality wise possibly superior.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 22, 2019

Unifont is a bitmap font specifically designed for 15px height. TTF format doesn't support bitmap font, it converts pixels to strokes, so there's a loss in accuracy in the process (bitmap fonts are best to be used as PCF). That's typically a case where hinting can help.

A font without hinting will look bad on any size it hasn't been designed for. That's its normal behavior.

What should be noted here: not all fonts should suit all sizes, that's totally normal and highly depends on the design of the font. You can't expect a rasterizer to do what a font doesn't. Unless it has a good hinting.

If we want to correctly compare StbSharp and Freetype, we should select a group of fonts with and without hinting, and compare the results with and without anti-aliasing at the pt sizes for which the fonts has been designed for.

I'm not trying to go against any of the lib either, but I do care about fonts being perfectly rendered at their intended sizes (better rendering at non-intended size is icing on the cake).

@Jjagg

This comment has been minimized.

Copy link
Contributor

commented Jan 22, 2019

@willmotil That's ridiculous. You can't expect a pixel-perfect font to look good at all sizes. There's only so many pixels 🤷‍♂
Of course you're supposed to know what size to render a pixel-perfect font at. You got it off the internet somewhere, so the right size is gonna be included on the web page or whatever.

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Jan 23, 2019

I also don't support any lib.
However there's one additional benefit of using stb_truetype I've found recently: fontstash uses it.
I've already ported fontstash to C# and integrated into the SpriteFontPlus, and latter can now render fonts on demand to the texture atlas(https://github.com/rds1983/SpriteFontPlus#dynamicspritefont).

So if MonoGame considers gaining similar feature through FontStashSharp, then stb_truetype is the choice.

@tomspilman

This comment has been minimized.

Copy link
Member

commented Jan 23, 2019

I would love to see us use something like stb_truetype vs freetype... quality and performance are my main concerns. And for sure whatever we decide on for runtime use should be used to replace our existing offline font generation in the Pipeline.

@Jjagg

This comment has been minimized.

Copy link
Contributor

commented Jan 23, 2019

@rds1983 The API with the dynamic font is awesome. Would love to get that into MG.
@tomspilman There's a trade-off to make. FreeType can produce higher quality glyphs, but it's bigger and it's a native lib. FreeType makes sense for offline, but maybe stb_truetype is better for online glyph rasterizing. I see the fact that StbSharp doesn't require additional native dependencies as a big advantage, which makes it more interesting as the runtime solution IMO.

@willmotil

This comment has been minimized.

Copy link
Contributor

commented Jan 23, 2019

Another thing to note even though stb would seem more performant as its smaller from what i've read it can take up to 2x or 3x as long to rasterize the pixels.
.
.

Unifont is a bitmap font specifically designed for 15px height.

It has artifacts at point size 8 9 10 11 ** 13 14 (15) 16 all the way up to 23
It only renders properly at point size 12. and 24.
Other bmp fonts produced the same behavior including one i created myself to double check.

That's ridiculous. You can't expect a pixel-perfect font to look good at all sizes.

You're missing the point.

It should still render at least as good at a higher point size then a lower one.
Why should a 15pt size font render perfectly at 12pt then start missing pixels at higher point sizes ?

Also

This maybe just due to aliasing maybe not i still cant turn it off if it is.

If the above is just going to be considered a (non problem).
Since there are plenty of people using bmp fonts and as this truetype doesn't turn a 0 into a e at any size or J's into I's . Then i consider the notion of quality here to be subjective.

@rds1983

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2019

Btw, I have considered possibility of porting freetype to C#.
However big amount of different source files scared me off. Especially as far as I understand not all of them are required in the gamedev.
So if someone will give me list of freetype source files that are used in gamedev.
Along with list of required defines.
I'll give it a try of converting. Though can't guarantee success.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2019

Not sure if it's worth trying to port freetype to C#. Having a pure C# library with no dependency sure is a great help, but if we ever do down the freetype road, I believe we should be fine with the native library. It builds finely on all platforms including consoles.

The only important thing to keep in mind, is to not load the library unless dynamic fonts are used, so that developers who don't use it can skip on shipping the freetype binaries with their games.

What about trying to add hinting support to stb_truetype? I haven't look into this myself, so I don't know how much work this represents.

@willmotil

This comment has been minimized.

Copy link
Contributor

commented Jan 24, 2019

What about trying to add hinting support to stb_truetype? I haven't look into this myself, so I don't know how much work this represents.

Well the code is all exposed so.

For hinted fonts.

They have hint pixels embedded in the ttf and those would need to be extracted.
Since they are embedded there must be a algorithm to also render them.

I guess its a 2 part problem.

Find the instructions on how to read hinting pixels from a ttf.
(i have no idea were to find that information.)
Then finding the rules for implementing the interpolated designated hint pixels
(that might be a curved interpolation based on a polynominal or something still shouldn't be too hard).

So getting the hinting data out of the ttf file would be the hard part.

.
.

For un-hinted fonts

Since they don't have hinted pixels, I guess one could just write a algorithm i suppose that should be fairly easy.
Edit this is not so easy as i thought it would be, i gave it a shot today there was some things involved i didn't consider at least from the side of just making my own sharpening filter on the output end.

Pixels[] // index0 rgba = pixels[ 0 to 4 ]

            var rgb = new Color[Width * Height];
            for (var i = 0; i < Pixels.Length; ++i)
            {
                var b = Pixels[i];
                rgb[i].R = b;
                rgb[i].G = b;
                rgb[i].B = b;
                rgb[i].A = b;
            }
           // filter the data to sharpen it.
           
            // set the data.
@stromkos

This comment has been minimized.

Copy link
Contributor

commented Jan 28, 2019

I have prepared a gist to provide native dynamic font support to Android . I have a less performant one for Windows.(it seems to slow down at about 230 dynamically generated characters per step), but the Android variant given has lasted over 30 minutes without any performance degradation. This solution allows any valid text on the system to render including Color Emojis, and all three flags of Scotland, England, and Whales.(Not possible with a basic UTF32 encoding(Since, each requires multiple UTF-32 chars to render.))
Please note than I am not purposing that this code should be included in the framework, merely that the code should be available to those that use it.

@Jure-BB

This comment has been minimized.

Copy link
Contributor

commented Jan 30, 2019

I have also implemented something like this in my game. Unfortunately, the code is a bit of a mess and coupled to the engine. It works, but it was not written with intention to be a general library. But I could share the relevant pieces, if needed.

My vote goes to FreeType as it is fast, feature rich, multi-platform and well tested library. Good font rasterization is not that easy.

Since scaling is quite common effect in games, it may be worth considering to store rasterized glyphs in SDF (Signed Distance Field) format. This would make text rendering even more flexible. However, I'm not sure if SDF is good for small text, were pixel-perfect precision is needed. I haven't implemented SDF myself.
With FreeType we could also add support for outlined fonts.

Regarding the implementation, would we do rasterization at load time or on-the-fly?

Pros of load-time rasterization is that it can't slow down the game while running and that we know exact dimensions of the texture atlas that we need. But this might not work that well for Asian fonts with lots of characters.

We could also do combination of both. Load time rasterizaton for predefined list of chars and rasterize additional glyphs on-the-fly, if needed. Problem becomes, what size do we need for a texture atlas. We could use shared texture atlases, but this could lead to unecesary texture switching when rendering single line of text. Although this would only happen, if glyph, that was rasterized at later time, has been placed in a new atlas as the old atlas (where the rest of the glyphs for that font are) got full. Shared atlases would be more efficient memory-wise.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 30, 2019

SDF isn't quite helpful for small/pixel fonts, but yeah, I agree that having the option to render fonts using SDF is a huge plus. Any modern game uses SDF rendering when it comes to very accurate HD texts.

I think that using or not using SDF rasterizing & rendering should be switch.

@Apostolique

This comment has been minimized.

Copy link

commented Jan 30, 2019

There's this repo that looks really interesting: https://github.com/LayoutFarm/Typography

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Jan 31, 2019

Typography sounds promising, unfortunately it is not usable as of now. I've been playing around with it for our ongoing project and there is a few missing features which make some fonts to crash upon loading with NotImplementedException. Maybe in the long run.

@Apostolique

This comment has been minimized.

Copy link

commented Jan 31, 2019

Have the features already been submitted in their issues?

@ryancheung

This comment has been minimized.

Copy link

commented Mar 3, 2019

I found SkiaSharp seems have the ability to handle dynamic CJK fonts in MonoGame.
I plan to use SkiaSharp to render fonts to Bitmap image, and create a texture and render it.

This may not be related to implementing dynamic ttf SpriteFont support.
But I want to check if someone have done this as a workaround before dynamic ttf support added to MonoGame.

SkiaSharp should be able to replace the entire System.Drawing or System.Drawing.Image that are not corss-platform friendly.
SkiaSharp also provide full featured text formating support, e.g. TextAlignment, which have no support in MG for now.

Does anyone have been to this approach?

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Mar 3, 2019

Back when I looked at SkiaSharp, it had a dependency toward System.Drawing and GDI+, which makes it a mess to be cross-platform. I don't know if it's still the case, though.

If you have any feedback regarding SkiaSharp, it is very welcome. Our main concern is to have little to no dependencies.

@ryancheung

This comment has been minimized.

Copy link

commented Mar 3, 2019

I'd checke the source code. Only projects in SkiaSharp.Views directory, SkiaSharp.Desktop and SkiaSharp.HarfBuzz.Desktop project have dependency on System.Drawing, and they are used for build desktop or mobile app with Skia or SkiaSharp.

It should be OK with us, we just need the core SkiaSharp libraries.

@mrhelmut

This comment has been minimized.

Copy link
Contributor

commented Mar 4, 2019

Took a closer look at it, and SkiaSharp is a binding for the native Skia, which makes it less workable.
If we have to rely on a native dependency, it would probably be more reliable to work with freetype (which I know works just fine on consoles).

@willmotil

This comment has been minimized.

Copy link
Contributor

commented May 16, 2019

Did anyone figure out if its possible to tell freetype to turn off its aliasing when it renders for spritefont ?

@ryancheung

This comment has been minimized.

Copy link

commented May 17, 2019

I've been using SkiaSharp for a long timenow, and found libskia has lot of brilliant text rendering features and works every well on desktop and mobile.

The text rendered in skia looks greater than any SpriteFont-like feature(I compared with dynamic font rendering feature of Xenko).

For anyone has to render lot of texts(especially CJK small font texts), I recommend to use SkiaSharp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.