LocalizedFontProcessor.cs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // LocalizedFontProcessor.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System.IO;
  11. using System.Xml;
  12. using Microsoft.Xna.Framework.Content.Pipeline;
  13. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  14. using Microsoft.Xna.Framework.Content.Pipeline.Processors;
  15. #endregion
  16. namespace LocalizationPipeline
  17. {
  18. /// <summary>
  19. /// Custom processor extends the SpriteFont build process to scan over the resource
  20. /// strings used by the game, automatically adding whatever characters it finds in
  21. /// them to the font. This makes sure the game will always have all the characters
  22. /// it needs, no matter what languages it is localized into, while still producing
  23. /// an efficient font that does not waste space on unnecessary characters. This is
  24. /// especially useful for languages such as Japanese and Korean, which have
  25. /// potentially thousands of different characters, although games typically only
  26. /// use a small fraction of these. Building only the characters we need is far more
  27. /// efficient than if we tried to include the entire CJK character region.
  28. /// </summary>
  29. [ContentProcessor]
  30. class LocalizedFontProcessor : ContentProcessor<LocalizedFontDescription,
  31. SpriteFontContent>
  32. {
  33. /// <summary>
  34. /// Converts a font description into SpriteFont format.
  35. /// </summary>
  36. public override SpriteFontContent Process(LocalizedFontDescription input,
  37. ContentProcessorContext context)
  38. {
  39. // Scan each .resx file in turn.
  40. foreach (string resourceFile in input.ResourceFiles)
  41. {
  42. string absolutePath = Path.GetFullPath(resourceFile);
  43. // Make sure the .resx file really does exist.
  44. if (!File.Exists(absolutePath))
  45. {
  46. throw new InvalidContentException("Can't find " + absolutePath);
  47. }
  48. // Load the .resx data.
  49. XmlDocument xmlDocument = new XmlDocument();
  50. xmlDocument.Load(absolutePath);
  51. // Scan each string from the .resx file.
  52. foreach (XmlNode xmlNode in xmlDocument.SelectNodes("root/data/value"))
  53. {
  54. string resourceString = xmlNode.InnerText;
  55. // Scan each character of the string.
  56. foreach (char usedCharacter in resourceString)
  57. {
  58. input.Characters.Add(usedCharacter);
  59. }
  60. }
  61. // Mark that this font should be rebuilt if the resource file changes.
  62. context.AddDependency(absolutePath);
  63. }
  64. // After adding the necessary characters, we can use the built in
  65. // FontDescriptionProcessor to do the hard work of building the font for us.
  66. return context.Convert<FontDescription,
  67. SpriteFontContent>(input, "FontDescriptionProcessor");
  68. }
  69. }
  70. }