How to draw every characters with spritefont in monogame

2.6k views Asked by At

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.

2

There are 2 answers

0
J3soon On BEST ANSWER

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.)

1
Team Shuriken On

I was not able to reproduce the steps of the accepted answer from J3soon in Monogame 3.7.1.

However in Monogame 3.7.1, it is not longer necessary to use the Custom Content Pipeline because the pipeline tool now natively contains a LocalizedFontProcessor.

My steps were :

  1. Set the .spritefont Processor to LocalizedFontProcessor in the pipeline tool
  2. In the .spritefont, include the path to the resx file.
  3. In the .spritefont, replace Asset Type="Graphics:FontDescription" with Asset Type="Graphics:LocalizedFontDescription"
  4. Rebuild the Content

I would have thought step #1 would have done #3 behind the scenes but for me it was necessary to do this both in the pipeline tool and the .spritefont file.

spritefont file

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

Content file

#begin MyFont.spritefont
/importer:FontDescriptionImporter
/processor:LocalizedFontProcessor
/processorParam:PremultiplyAlpha=True
/processorParam:TextureFormat=Compressed
/build:MyFont.spritefont