LocalizedFontProcessor.cs 3.4 KB

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