2012-10-22 17:18:04 +00:00
#region Using Statements
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
2012-10-28 18:33:54 +00:00
using System.Drawing ;
using System.Globalization ;
2012-10-19 21:59:35 +00:00
using System.IO ;
2012-10-28 18:33:54 +00:00
using System.Runtime.InteropServices ;
using System.Xml ;
2012-10-22 17:18:04 +00:00
using System.Xml.Linq ;
2012-10-19 21:59:35 +00:00
using ANX.Framework.Content.Pipeline.Graphics ;
using ANX.Framework.NonXNA.Development ;
2012-10-22 17:18:04 +00:00
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
2012-10-19 21:59:35 +00:00
namespace ANX.Framework.Content.Pipeline.Importer
{
/// <summary>Provides methods for reading .spritefont files for use in the Content Pipeline.</summary>
2012-10-28 18:33:54 +00:00
[PercentageComplete(90)]
2012-10-19 21:59:35 +00:00
[Developer("SilentWarrior/Eagle Eye Studios")]
2012-10-28 18:33:54 +00:00
[TestState(TestStateAttribute.TestState.InProgress)] //Works but there should be a check whether the characters are supported
[ContentImporter("Spritefont", ".spritefont", DefaultProcessor = "FontDescriptionProcessor", DisplayName = "FontDescription Importer - ANX Framework")]
2012-10-19 21:59:35 +00:00
public class FontDescriptionImporter : ContentImporter < FontDescription >
{
2012-10-22 17:18:04 +00:00
private static ContentBuildLogger _logger ;
2012-10-19 21:59:35 +00:00
/// <summary>Called by the Framework when importing a .spritefont file to be used as a game asset. This is the method called by the Framework when an asset is to be imported into an object that can be recognized by the Content Pipeline.</summary>
/// <param name="filename">Name of a game asset file.</param>
/// <param name="context">Contains information for importing a game asset, such as a logger interface.</param>
public override FontDescription Import ( string filename , ContentImporterContext context )
{
2012-10-22 17:18:04 +00:00
_logger = context . Logger ;
var doc = XDocument . Load ( filename ) ;
FontDescription fontDescription = DeserializeFont ( doc ) ;
fontDescription . Identity = new ContentIdentity ( new FileInfo ( filename ) . FullName ,
"FontDescriptionImporter" ) ;
2012-10-19 21:59:35 +00:00
return fontDescription ;
}
2012-10-28 18:33:54 +00:00
2012-10-22 17:18:04 +00:00
private static FontDescription DeserializeFont ( XContainer xDoc )
2012-10-19 21:59:35 +00:00
{
2012-10-28 18:33:54 +00:00
//Check if either the XnaContent or the AnxContent attribute exists.
2012-10-22 17:18:04 +00:00
var tag = xDoc . Element ( "XnaContent" ) ;
if ( tag = = null )
{
tag = xDoc . Element ( "AnxContent" ) ;
if ( tag = = null )
throw new InvalidContentException (
"The Xml file does not contain a valid XnaContent or AnxContent tag." ) ;
}
2012-10-28 18:33:54 +00:00
//Check for asset element to ensure this is XNA content
2012-10-22 17:18:04 +00:00
var assetNode = tag . Element ( "Asset" ) ;
if ( assetNode = = null )
throw new InvalidContentException ( "No valid Asset element in xml source." ) ;
2012-10-28 18:33:54 +00:00
//Only accept assets with type FontDescription
2012-10-22 17:18:04 +00:00
var xAttribute = assetNode . Attribute ( "Type" ) ;
if ( xAttribute = = null | | xAttribute . Value ! = "Graphics:FontDescription" )
2012-10-28 18:33:54 +00:00
throw new InvalidContentException ( "This is not a font description!" ) ;
2012-10-22 17:18:04 +00:00
2012-10-28 18:33:54 +00:00
//Check if the font name was specified
2012-10-22 17:18:04 +00:00
var fontNameElement = assetNode . Element ( "FontName" ) ;
if ( fontNameElement = = null )
throw new InvalidContentException ( "No font name specified in xml source." ) ;
2012-10-28 18:33:54 +00:00
var fontName = fontNameElement . Value ; // if there is a font name, store it
2012-10-22 17:18:04 +00:00
2012-10-28 18:33:54 +00:00
//Same as above, except with a conversion of the size.
2012-10-22 17:18:04 +00:00
var sizeElement = assetNode . Element ( "Size" ) ;
if ( sizeElement = = null )
throw new InvalidContentException ( "No font size specified in xml source." ) ;
var fontSize = Convert . ToInt32 ( sizeElement . Value ) ;
2012-10-28 18:33:54 +00:00
//Check and convert the spacing
2012-10-22 17:18:04 +00:00
var spacingElement = assetNode . Element ( "Spacing" ) ;
if ( spacingElement = = null )
throw new InvalidContentException ( "Spacing is not defined in xml source." ) ;
var fontSpacing = Convert . ToInt32 ( spacingElement . Value ) ;
2012-10-28 18:33:54 +00:00
//Check for style element and try to parse it.
2012-10-22 17:18:04 +00:00
var styleElement = assetNode . Element ( "Style" ) ;
if ( styleElement = = null )
throw new InvalidContentException ( "No style specified in xml source." ) ;
FontDescriptionStyle fontStyle ;
Enum . TryParse ( styleElement . Value , out fontStyle ) ;
2012-10-28 18:33:54 +00:00
//Get the character regions element to iterate through the character regions
2012-10-22 17:18:04 +00:00
var charRegionsElement = assetNode . Element ( "CharacterRegions" ) ;
if ( charRegionsElement = = null )
throw new InvalidContentException ( "No character region specified in xml source" ) ;
var fontCharRegions = charRegionsElement . Elements ( "CharacterRegion" ) ;
2012-10-28 18:33:54 +00:00
var characters = new List < char > ( ) ; //The list that will be passed to the processor
foreach ( var fontCharRegion in fontCharRegions )
2012-10-22 17:18:04 +00:00
{
2012-10-28 18:33:54 +00:00
//for each char declaration get the start and end elements
2012-10-22 17:18:04 +00:00
var startElement = fontCharRegion . Element ( "Start" ) ;
if ( startElement = = null )
throw new InvalidContentException ( "Character region is invalid. Start element is missing!" ) ;
var endElement = fontCharRegion . Element ( "End" ) ;
if ( endElement = = null )
throw new InvalidContentException ( "Character region is invalid. Start element is missing!" ) ;
2012-10-28 18:33:54 +00:00
int startChar ;
int endChar ;
//Convert the chars back to hex values, silly xml importer reads them as chars, int value '32' equals an empty string or hex value #32
startChar = String . IsNullOrEmpty ( startElement . Value ) ? 32 : Convert . ToInt32 ( Convert . ToChar ( startElement . Value ) ) ;
endChar = Convert . ToInt32 ( Convert . ToChar ( endElement . Value ) ) ;
_logger . LogMessage ( "Start: '" + startElement . Value + "' (" + startChar + ")" ) ;
_logger . LogMessage ( "End: '" + endElement . Value + "' (" + endChar + ")" ) ;
//Check if the chars are within ASCII range
if ( ( startChar > = endChar ) | |
( startChar < 0 ) | | ( startChar > 0xFFFF ) | |
( endChar < 0 ) | | ( endChar > 0xFFFF ) )
{
throw new ArgumentException ( "Invalid character range " +
startElement . Value + " - " + endElement . Value ) ;
}
//add each char from the range to the list
for ( var i = startChar ; i < endChar - 1 ; i + + )
{
characters . Add ( Convert . ToChar ( i ) ) ;
}
//Debugger.Break();
//TODO: We need a platform independet solution for checking the characters supported by a font! For now we pass it.
2012-10-22 17:18:04 +00:00
}
2012-10-28 18:33:54 +00:00
_logger . LogMessage ( "Import of SpriteFont finished." ) ;
2012-10-22 17:18:04 +00:00
var result = new FontDescription ( fontName , fontSize , fontSpacing , fontStyle )
{
Characters = characters
} ;
return result ;
2012-10-19 21:59:35 +00:00
}
}
}