#region File Description //----------------------------------------------------------------------------- // LocalizedFontProcessor.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Graphics; using System.IO; using System.Xml; #endregion namespace LocalizationPipeline { /// /// Custom processor extends the SpriteFont build process to scan over the resource /// strings used by the game, automatically adding whatever characters it finds in /// them to the font. This makes sure the game will always have all the characters /// it needs, no matter what languages it is localized into, while still producing /// an efficient font that does not waste space on unnecessary characters. This is /// especially useful for languages such as Japanese and Korean, which have /// potentially thousands of different characters, although games typically only /// use a small fraction of these. Building only the characters we need is far more /// efficient than if we tried to include the entire CJK character region. /// [ContentProcessor] class LocalizedFontProcessor : ContentProcessor { /// /// Converts a font description into SpriteFont format. /// public override SpriteFontContent Process(LocalizedFontDescription input, ContentProcessorContext context) { GetLocalisedResX(input, context); // After adding the necessary characters, we can use the built in // FontDescriptionProcessor to do the hard work of building the font for us. return context.Convert(input, "FontDescriptionProcessor"); } private static void GetLocalisedResX(LocalizedFontDescription input, ContentProcessorContext context) { // Scan each .resx file in turn. foreach (string resourceFile in input.ResourceFiles) { string absolutePath = Path.GetFullPath(resourceFile); // Make sure the .resx file really does exist. if (!File.Exists(absolutePath)) { throw new InvalidContentException("Can't find " + absolutePath); } // Load the .resx data. XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(absolutePath); // Scan each string from the .resx file. foreach (XmlNode xmlNode in xmlDocument.SelectNodes("root/data/value")) { string resourceString = xmlNode.InnerText; // Scan each character of the string. foreach (char usedCharacter in resourceString) { input.Characters.Add(usedCharacter); } } // Mark that this font should be rebuilt if the resource file changes. context.AddDependency(absolutePath); } } } }