Search code examples
c#fontsxnamonogamespritefont

How to draw every characters with spritefont in monogame


I'm new to monogame, and I'm trying to make a .spritefont file in order to draw string with the font I choose.

Strings with English characters can show well on the screen, but I wish to draw strings in multiple languages, like Japanese and Chinese.

So, I tried to load all characters in a Multi Language Font "Microsoft JhengHei".

The font's first character is !(U+0021) and the last one is ○(U+FFEE).

But when I tried to compile the program, the compiler gave me an error:

.../Content/MyFont.spritefont : error : Importer 'FontDescriptionImporter' had unexpected failure!

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: CharacterRegion.End must be greater than CharacterRegion.Start

at Microsoft.Xna.Framework.Content.Pipeline.Graphics.FontDescription.set_CharacterRegions(CharacterRegion[] value)

And when I changed the ○ to 忮, MSBuild stucks and takes forever to proceed the content.

Code in MyFont.spritefont below:

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
  <Asset Type="Graphics:FontDescription">
    <FontName>Microsoft JhengHei</FontName>
    <Size>14</Size>
    <Spacing>0</Spacing>
    <UseKerning>true</UseKerning>
    <Style>Regular</Style>
    <CharacterRegions>
      <CharacterRegion>
        <Start>&#x0021;</Start>
        <End>&#xFFEE;</End>
      </CharacterRegion>
    </CharacterRegions>
  </Asset>
</XnaContent>

I searched for the solution for a few days but in vain, any help is appreciated.


Solution

  • Since processing all 65 thousand characters takes too much time. We should only process the characters we are using.

    So the easiest way is to make a MonoGame Custom Content Pipeline and load the characters we are using by some .resx files.

    It took me so much time searching for this solution. So I'll post how did I succeed, hope it can help someone who has the same question in the future.

    Step-by-step Tutorial

    1. Create a Class Library.

    2. Reference the MonoGame.Framework.Content.Pipeline.Portable package using NuGet. (Make sure you checked the Include Prerelease checkbox )

    3. Download the LocalizationSample here and unzip the file.

    4. Under LocalizationPipeline\ copy LocalizedFontDescription.cs and LocalizedFontProcessor.cs into the class library

    5. Build the class library so it outputs a LocalizationPipeline.dll file.

    6. Open Myfont.spritefont and change its Asset Type to LocalizationPipeline.LocalizedFontDescription

    7. Then add the resources <ResourceFiles><Resx>..\strings.resx</Resx></ResourceFiles> (these files should contain the string we want to draw)

    8. Open Content.mgcb and reference to LocalizationPipeline.dll

    9. Set the MyFont.spritefont's processor to LocalizedFontProcessor

    10. ReBuild the project.

    MyFont.spritefont

    <?xml version="1.0" encoding="utf-8"?>
    <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
      <Asset Type="LocalizationPipeline.LocalizedFontDescription">
        <FontName>Microsoft JhengHei</FontName>
        <Size>14</Size>
        <Spacing>0</Spacing>
        <UseKerning>true</UseKerning>
        <Style>Regular</Style>
        <CharacterRegions>
          <CharacterRegion>
            <Start>&#32;</Start>
            <End>&#126;</End>
          </CharacterRegion>
        </CharacterRegions>
        <ResourceFiles>
          <Resx>..\strings.resx</Resx>
        </ResourceFiles>
      </Asset>
    </XnaContent>
    

    Content.mgcb

    ...
    #-------------------------------- References --------------------------------#
    
    /reference:..\LocalizationPipeline.dll
    
    #---------------------------------- Content ---------------------------------#
    ...
    #begin MyFont.spritefont
    /importer:FontDescriptionImporter
    /processor:LocalizedFontProcessor
    /build:MyFont.spritefont
    ...
    

    Sources

    1. Part 1 of Creating custom content importers for the MonoGame Pipeline

    2. How to: Create a Localized Game

    3. LocalizationSample (Thanks to @Groo for giving me this link.)