CompositeFontParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / MS / Internal / FontFace / CompositeFontParser.cs / 1 / CompositeFontParser.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Contents:  The XML Composite font parsing 
//
// Created:   6-11-2003 Tarek Mahmoud Sayed ([....]) 
// 
//---------------------------------------------------------------------------
 
using System;
using System.IO;
using System.Security;
using System.Security.Permissions; 
using System.Text;
using System.Windows; 
using System.Windows.Media; 
using System.Windows.Markup;
using System.Xml; 
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 
using MS.Internal.TextFormatting;
 
using System.Reflection; 

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;

namespace MS.Internal.FontFace
{ 
    internal class CompositeFontParser
    { 
        internal static void VerifyMultiplierOfEm(string propertyName, ref double value) 
        {
            if (DoubleUtil.IsNaN(value)) 
            {
                throw new ArgumentException(SR.Get(SRID.PropertyValueCannotBeNaN, propertyName));
            }
            else if (value > Constants.GreatestMutiplierOfEm) 
            {
                value = Constants.GreatestMutiplierOfEm; 
            } 
            else if (value < -Constants.GreatestMutiplierOfEm)
            { 
                value = -Constants.GreatestMutiplierOfEm;
            }
        }
 
        internal static void VerifyPositiveMultiplierOfEm(string propertyName, ref double value)
        { 
            if (DoubleUtil.IsNaN(value)) 
            {
                throw new ArgumentException(SR.Get(SRID.PropertyValueCannotBeNaN, propertyName)); 
            }
            else if (value > Constants.GreatestMutiplierOfEm)
            {
                value = Constants.GreatestMutiplierOfEm; 
            }
            else if (value <= 0) 
            { 
                throw new ArgumentException(SR.Get(SRID.PropertyMustBeGreaterThanZero, propertyName));
            } 
        }

        internal static void VerifyNonNegativeMultiplierOfEm(string propertyName, ref double value)
        { 
            if (DoubleUtil.IsNaN(value))
            { 
                throw new ArgumentException(SR.Get(SRID.PropertyValueCannotBeNaN, propertyName)); 
            }
            else if (value > Constants.GreatestMutiplierOfEm) 
            {
                value = Constants.GreatestMutiplierOfEm;
            }
            else if (value < 0) 
            {
                throw new ArgumentException(SR.Get(SRID.PropertyCannotBeNegative, propertyName)); 
            } 
        }
 
        private double GetAttributeAsDouble()
        {
            object value = null;
 
            try
            { 
                value = _doubleTypeConverter.ConvertFromString( 
                    null, // type converter context
                    _englishUSCulture, 
                    GetAttributeValue()
                    );
            }
            catch (NotSupportedException) 
            {
                FailAttributeValue(); 
            } 

            if (value == null) 
                FailAttributeValue();

            return (double)value;
        } 

        private XmlLanguage GetAttributeAsXmlLanguage() 
        { 
            object value = null;
 
            try
            {
                value = _xmlLanguageTypeConverter.ConvertFromString(
                    null, // type converter context 
                    _englishUSCulture,
                    GetAttributeValue() 
                    ); 
            }
            catch (NotSupportedException) 
            {
                FailAttributeValue();
            }
 
            if (value == null)
                FailAttributeValue(); 
 
            return (XmlLanguage)value;
        } 

        /// 
        /// Gets the value of the value of the current node which is assumed to be an
        /// attribute. Checks for markup expressions or escaped braces. 
        /// 
        private string GetAttributeValue() 
        { 
            string s = _reader.Value;
            if (string.IsNullOrEmpty(s)) 
                return string.Empty;

            if (s[0] == '{')
            { 
                if (s.Length > 1 && s[1] == '}')
                { 
                    s = s.Substring(2); 
                }
                else 
                {
                    FailAttributeValue();
                }
            } 

            return s; 
        } 

        private const NumberStyles UnsignedDecimalPointStyle = 
            NumberStyles.AllowTrailingWhite |
            NumberStyles.AllowLeadingWhite  |
            NumberStyles.AllowDecimalPoint;
 
        private const NumberStyles SignedDecimalPointStyle = UnsignedDecimalPointStyle | NumberStyles.AllowLeadingSign;
 
        ///  
        /// Reads the specified composite font file.
        ///  
        internal static CompositeFontInfo LoadXml(Stream fileStream)
        {
            CompositeFontParser parser = new CompositeFontParser(fileStream);
            return parser._compositeFontInfo; 
        }
 
        ///  
        /// Constructs the composite font parser and parses the file.
        ///  
        /// File stream to parse.
        private CompositeFontParser(Stream fileStream)
        {
            _compositeFontInfo = new CompositeFontInfo(); 

            _namespaceMap = new Hashtable(); 
            _englishUSCulture = CultureInfo.GetCultureInfoByIetfLanguageTag("en-US"); 
            _doubleTypeConverter = TypeDescriptor.GetConverter(typeof(double));
            _xmlLanguageTypeConverter = new System.Windows.Markup.XmlLanguageConverter(); 

            _reader = CreateXmlReader(fileStream);

            try 
            {
                if (IsStartElement(FontFamilyElement, CompositeFontNamespace)) 
                { 
                    ParseFontFamilyElement();
                } 
                else
                {
                    FailUnknownElement();
                } 
            }
            catch (XmlException x) 
            { 
                FailNotWellFormed(x);
            } 
            catch (XmlSyntaxException x)
            {
                FailNotWellFormed(x);
            } 
            catch (FormatException x)
            { 
                if (_reader.NodeType == XmlNodeType.Attribute) 
                    FailAttributeValue(x);
                else 
                    Fail(x.Message, x);
            }
            catch (ArgumentException x)
            { 
                if (_reader.NodeType == XmlNodeType.Attribute)
                    FailAttributeValue(x); 
                else 
                    Fail(x.Message, x);
            } 
            finally
            {
                _reader.Close();
                _reader = null; 
            }
        } 
 

        ///  
        /// Creates the XML reader for the specified file.
        /// 
        private XmlReader CreateXmlReader(Stream fileStream)
        { 
            XmlReaderSettings settings = new XmlReaderSettings();
 
            settings.CloseInput = true; 
            settings.IgnoreComments = true;
            settings.IgnoreWhitespace = false; 
            settings.ProhibitDtd = true;

            XmlReader baseReader = XmlReader.Create(fileStream, settings);
 
            return new XmlCompatibilityReader(baseReader, new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported));
        } 
 

        ///  
        /// Determines whether a given XML namespace is "known" (i.e., should always be processed)
        /// or "unknown" (i.e., should be skipped if declared ignorable).
        /// 
        /// XML namespace to look up. 
        /// Other namespace to map to, if any. Used for versioning.
        /// This implementation always returns null in this parameter. 
        ///  
        /// Returns true ("known") for the XAML namespace or the composite font namespace.
        /// for which a Mapping PI exists. 
        /// 
        /// 
        /// System.String is the only object in a mapped namespace that we can instantiate. However,
        /// we don't want to ignore any mapped namespaces for compatibility reasons. In general, it's 
        /// better for us to reject valid XAML than to accept invalid XAML. We therefore don't want
        /// to ignore an element which the XAML parser would not ignore -- the ignored element might 
        /// be invalid. If mapped elements other than System.String are needed in future versions, a 
        /// composite font author can achieve backwards compatibility by conditionalizing mapped
        /// elements using c:AlternateContent markup. 
        /// 
        private bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace)
        {
            newXmlNamespace = null; 
            return xmlNamespace == CompositeFontNamespace ||
                xmlNamespace == XamlNamespace || 
                IsMappedNamespace(xmlNamespace); 
        }
 
        /// 
        /// Calls MoveToContent and checks whether the reader is positioned on the specified element.
        /// 
        ///  
        /// We should always call this method instead of calling _reader.IsStartElement directly because
        /// the latter calls MoveToContent on the underlying reader which means we could fail to parse 
        /// Mapping processing instructions. 
        /// 
        private bool IsStartElement(string localName, string namespaceURI) 
        {
            MoveToContent();
            return _reader.IsStartElement(localName, namespaceURI);
        } 

        ///  
        /// Same semantics as XmlReader.MoveToContent, but this method processes Mapping processing 
        /// instructions as it advances past them.
        ///  
        private XmlNodeType MoveToContent()
        {
            bool contentNode = false;
 
            do
            { 
                switch (_reader.NodeType) 
                {
                    case XmlNodeType.CDATA: 
                    case XmlNodeType.Element:
                    case XmlNodeType.EndElement:
                    case XmlNodeType.EntityReference:
                    case XmlNodeType.EndEntity: 
                        contentNode = true;
                        break; 
                } 
            } while (!contentNode && _reader.Read());
 
            return _reader.NodeType;
        }

        #region ProcessingInstructions 

       private bool IsMappedNamespace(string xmlNamespace) 
        { 
            return _namespaceMap.ContainsKey(xmlNamespace);
        } 

        private bool IsSystemNamespace(string xmlNamespace)
        {
            return (xmlNamespace == "clr-namespace:System;assembly=mscorlib"); 
        }
 
        #endregion ProcessingInstructions 

        ///  
        /// Parses the FontFamily element, including its attributes and children,
        /// and advances to the next sibling element.
        /// 
        private void ParseFontFamilyElement() 
        {
            // Iterate over the attributes. 
            if (_reader.MoveToFirstAttribute()) 
            {
                do 
                {
                    // Process attributes in the composite font namespace
                    if (IsCompositeFontAttribute())
                    { 
                        string name = _reader.LocalName;
 
                        if (name == BaselineAttribute) 
                        {
                            _compositeFontInfo.Baseline = GetAttributeAsDouble(); 
                        }
                        else if (name == LineSpacingAttribute)
                        {
                            _compositeFontInfo.LineSpacing = GetAttributeAsDouble(); 
                        }
                        else 
                        { 
                            FailUnknownAttribute();
                        } 
                    }
                    else if (!IsIgnorableAttribute())
                    {
                        FailUnknownAttribute(); 
                    }
 
                } while (_reader.MoveToNextAttribute()); 

                _reader.MoveToElement(); 
            }

            // Empty element?
            if (_reader.IsEmptyElement) 
            {
                VerifyCompositeFontInfo(); 
                _reader.Read(); 
                return;
            } 

            // Advance past the start tag.
            _reader.Read();
 
            // Iterate over children.
            while (MoveToContent() != XmlNodeType.EndElement) 
            { 
                if (_reader.NodeType == XmlNodeType.Element && _reader.NamespaceURI == CompositeFontNamespace)
                { 
                    bool isEmpty = _reader.IsEmptyElement;

                    // It's an element in the composite font namespace; branch depending on the name.
                    switch (_reader.LocalName) 
                    {
                        case FamilyNamesPropertyElement: 
                            VerifyNoAttributes(); 
                            _reader.Read();
                            if (!isEmpty) 
                            {
                                // Process all child elements.
                                while (MoveToContent() == XmlNodeType.Element)
                                { 
                                    if (_reader.LocalName == StringElement && IsSystemNamespace(_reader.NamespaceURI))
                                    { 
                                        // It's a System.String. 
                                        ParseFamilyNameElement();
                                    } 
                                    else
                                    {
                                        // Only System.String is valid in this context.
                                        FailUnknownElement(); 
                                    }
                                } 
 
                                // Advance past the  end element, or throw
                                // an exception if we're not at an end element. 
                                _reader.ReadEndElement();
                            }
                            break;
 
                        case FamilyTypefacesPropertyElement:
                            VerifyNoAttributes(); 
                            _reader.Read(); 
                            if (!isEmpty)
                            { 
                                // Process child elements, of which the only one we recognize in this
                                // context is FamilyTypeface.
                                while (IsStartElement(FamilyTypefaceElement, CompositeFontNamespace))
                                { 
                                    ParseFamilyTypefaceElement();
                                } 
 
                                // Advance past the  end element, or throw
                                // an exception if we're not at an end element. 
                                _reader.ReadEndElement();
                            }
                            break;
 
                        case FamilyMapsPropertyElement:
                            VerifyNoAttributes(); 
                            _reader.Read(); 
                            if (!isEmpty)
                            { 
                                // Process child elements, of which the only one we recognize in this
                                // context is FontFamilyMap.
                                while (IsStartElement(FamilyMapElement, CompositeFontNamespace))
                                { 
                                    ParseFamilyMapElement();
                                } 
 
                                // Advance past the  end element, or throw
                                // an exception if we're not at an end element. 
                                _reader.ReadEndElement();
                            }
                            break;
 
                        default:
                            // It's some other element. 
                            FailUnknownElement(); 
                            break;
                    } 
                }
                else
                {
                    // It's some other content besides an element in the composite font namespace; skip it. 
                    _reader.Skip();
                } 
            } 

            // We should now have read right up to the  end tag. 
            VerifyCompositeFontInfo();
            _reader.ReadEndElement();
        }
 
        /// 
        /// Makes sure the current element has no attributes (except ignorable ones). 
        ///  
        private void VerifyNoAttributes()
        { 
            if (_reader.MoveToFirstAttribute())
            {
                do
                { 
                    if (!IsIgnorableAttribute())
                        FailUnknownAttribute(); 
 
                } while (_reader.MoveToNextAttribute());
 
                _reader.MoveToElement();
            }
        }
 
        /// 
        /// Parses the FamilyName element (actually String), including its attributes 
        /// and children, and advances to the next sibling element. 
        /// 
        private void ParseFamilyNameElement() 
        {
            XmlLanguage language = null;

            // Iterate over the attributes. 
            if (_reader.MoveToFirstAttribute())
            { 
                do 
                {
                    if (_reader.NamespaceURI == XamlNamespace && _reader.LocalName == KeyAttribute) 
                    {
                        language = GetAttributeAsXmlLanguage();
                    }
                    else if (!IsIgnorableAttribute()) 
                    {
                        FailUnknownAttribute(); 
                    } 

                } while (_reader.MoveToNextAttribute()); 

                _reader.MoveToElement();
            }
 
            // XAML requires x:Key so we should, too.
            if (language == null) 
            { 
                FailMissingAttribute(LanguageAttribute);
            } 

            // The family name is the element content.
            string familyName = _reader.ReadElementString();
            if (string.IsNullOrEmpty(familyName)) 
            {
                FailMissingAttribute(NameAttribute); 
            } 

            _compositeFontInfo.FamilyNames.Add(language, familyName); 
        }

        /// 
        /// Parses the FamilyTypeface element, including its attributes and children, 
        /// and advances to the next sibling element.
        ///  
        private void ParseFamilyTypefaceElement() 
        {
            FamilyTypeface face = new FamilyTypeface(); 

            ParseFamilyTypefaceAttributes(face);

            if (_reader.IsEmptyElement) 
            {
                _reader.Read(); 
            } 
            else
            { 
                _reader.Read();

                while (MoveToContent() != XmlNodeType.EndElement)
                { 
                    if (_reader.NodeType == XmlNodeType.Element && _reader.NamespaceURI == CompositeFontNamespace)
                    { 
                        if (_reader.LocalName == DeviceFontCharacterMetricsPropertyElement) 
                        {
                            VerifyNoAttributes(); 

                            if (_reader.IsEmptyElement)
                            {
                                _reader.Read(); 
                            }
                            else 
                            { 
                                _reader.Read();
 
                                // Process all child elements.
                                while (MoveToContent() == XmlNodeType.Element)
                                {
                                    if (_reader.LocalName == CharacterMetricsElement) 
                                    {
                                        ParseCharacterMetricsElement(face); 
                                    } 
                                    else
                                    { 
                                        // Only CharacterMetricsElement is valid in this context.
                                        FailUnknownElement();
                                    }
                                } 
                                // Process the end element for the collection.
                                _reader.ReadEndElement(); 
                            } 
                        }
                        else 
                        {
                            FailUnknownElement();
                        }
                    } 
                    else
                    { 
                        _reader.Skip(); 
                    }
                } 

                _reader.ReadEndElement();
            }
 
            // Add the typeface.
            _compositeFontInfo.GetFamilyTypefaceList().Add(face); 
        } 

        ///  
        /// Parses the attributes of the FamilyTypeface element and sets the corresponding
        /// properties on the specified FamilyTypeface object. On return, the reader remains
        /// positioned on the element.
        ///  
        private void ParseFamilyTypefaceAttributes(FamilyTypeface face)
        { 
            // Iterate over the attributes. 
            if (_reader.MoveToFirstAttribute())
            { 
                do
                {
                    // Process attributes in the composite font namespace; ignore any others.
                    if (IsCompositeFontAttribute()) 
                    {
                        string name = _reader.LocalName; 
 
                        if (name == StyleAttribute)
                        { 
                            FontStyle fontStyle = new FontStyle();
                            if (!FontStyles.FontStyleStringToKnownStyle(GetAttributeValue(), CultureInfo.InvariantCulture, ref fontStyle))
                                FailAttributeValue();
 
                            face.Style = fontStyle;
                        } 
                        else if (name == WeightAttribute) 
                        {
                            FontWeight fontWeight = new FontWeight(); 
                            if (!FontWeights.FontWeightStringToKnownWeight(GetAttributeValue(), CultureInfo.InvariantCulture, ref fontWeight))
                                FailAttributeValue();

                            face.Weight = fontWeight; 
                        }
                        else if (name == StretchAttribute) 
                        { 
                            FontStretch fontStretch = new FontStretch();
                            if (!FontStretches.FontStretchStringToKnownStretch(GetAttributeValue(), CultureInfo.InvariantCulture, ref fontStretch)) 
                                FailAttributeValue();

                            face.Stretch = fontStretch;
                        } 
                        else if (name == UnderlinePositionAttribute)
                        { 
                            face.UnderlinePosition = GetAttributeAsDouble(); 
                        }
                        else if (name == UnderlineThicknessAttribute) 
                        {
                            face.UnderlineThickness = GetAttributeAsDouble();
                        }
                        else if (name == StrikethroughPositionAttribute) 
                        {
                            face.StrikethroughPosition = GetAttributeAsDouble(); 
                        } 
                        else if (name == StrikethroughThicknessAttribute)
                        { 
                            face.StrikethroughThickness = GetAttributeAsDouble();
                        }
                        else if (name == CapsHeightAttribute)
                        { 
                            face.CapsHeight = GetAttributeAsDouble();
                        } 
                        else if (name == XHeightAttribute) 
                        {
                            face.XHeight = GetAttributeAsDouble(); 
                        }
                        else if (name == DeviceFontNameAttribute)
                        {
                            face.DeviceFontName = GetAttributeValue(); 
                        }
                        else 
                        { 
                            FailUnknownAttribute();
                        } 
                    }
                    else if (!IsIgnorableAttribute())
                    {
                        FailUnknownAttribute(); 
                    }
 
                } while (_reader.MoveToNextAttribute()); 

                _reader.MoveToElement(); 
            }
        }

        ///  
        /// Parses a CharacterMetrics element, and advances the current position beyond the
        /// element. Adds a CharacterMetrics object to the given FamilyTypface. 
        ///  
        private void ParseCharacterMetricsElement(FamilyTypeface face)
        { 
            string key = null;
            string metrics = null;

            if (_reader.MoveToFirstAttribute()) 
            {
                do 
                { 
                    if (_reader.NamespaceURI == XamlNamespace && _reader.LocalName == KeyAttribute)
                    { 
                        key = GetAttributeValue();
                    }
                    else if (IsCompositeFontAttribute() && _reader.LocalName == MetricsAttribute)
                    { 
                        metrics = GetAttributeValue();
                    } 
                    else if (!IsIgnorableAttribute()) 
                    {
                        FailUnknownAttribute(); 
                    }
                } while (_reader.MoveToNextAttribute());

                _reader.MoveToElement(); 
            }
 
            if (key == null) 
                FailMissingAttribute(KeyAttribute);
 
            if (metrics == null)
                FailMissingAttribute(MetricsAttribute);

            face.DeviceFontCharacterMetrics.Add( 
                CharacterMetricsDictionary.ConvertKey(key),
                new CharacterMetrics(metrics) 
                ); 

            // There should be no child elements. 
            ParseEmptyElement();
        }

        ///  
        /// Parses the FontFamilyMap element, including its attributes and children,
        /// and advances to the next sibling element. 
        ///  
        private void ParseFamilyMapElement()
        { 
            FontFamilyMap fmap = new FontFamilyMap();

            // Parse the family map attributes.
            if (_reader.MoveToFirstAttribute()) 
            {
                do 
                { 
                    // Process attributes in the composite font namespace; ignore any others.
                    if (IsCompositeFontAttribute()) 
                    {
                        string name = _reader.LocalName;

                        if (name == UnicodeAttribute) 
                        {
                            fmap.Unicode = GetAttributeValue(); 
                        } 
                        else if (name == TargetAttribute)
                        { 
                            fmap.Target = GetAttributeValue();
                        }
                        else if (name == ScaleAttribute)
                        { 
                            fmap.Scale = GetAttributeAsDouble();
                        } 
                        else if (name == LanguageAttribute) 
                        {
                            fmap.Language = GetAttributeAsXmlLanguage(); 
                        }
                        else
                        {
                            FailUnknownAttribute(); 
                        }
                    } 
                    else if (!IsIgnorableAttribute()) 
                    {
                        FailUnknownAttribute(); 
                    }

                } while (_reader.MoveToNextAttribute());
 
                _reader.MoveToElement();
            } 
 
            _compositeFontInfo.FamilyMaps.Add(fmap);
 
            // There should be no child elements.
            ParseEmptyElement();
        }
 
        /// 
        /// Advances past the current element and its children, throwing and exception 
        /// if there are any child elements in the composite font namespace. 
        /// 
        private void ParseEmptyElement() 
        {
            if (_reader.IsEmptyElement)
            {
                _reader.Read(); 
                return;
            } 
 
            _reader.Read();
 
            while (MoveToContent() != XmlNodeType.EndElement)
            {
                if (_reader.NodeType == XmlNodeType.Element && _reader.NamespaceURI == CompositeFontNamespace)
                { 
                    FailUnknownElement();
                } 
                else 
                {
                    _reader.Skip(); 
                }
            }

            _reader.ReadEndElement(); 
        }
 
        ///  
        /// Determines whether the reader is positioned on an composite font attribute,
        /// which we define to me either (a) it has no namespace at all, or (b) it's in 
        /// the composite font namespace.
        /// 
        private bool IsCompositeFontAttribute()
        { 
            string ns = _reader.NamespaceURI;
            return string.IsNullOrEmpty(ns) || ns == CompositeFontNamespace; 
        } 

        ///  
        /// Determines whether the attribute can be safely ignored, even if it
        /// has not been explicitly declared as ignorable via compatibility markup.
        /// Currently, we ignore attributes defined by the XML and XML namespaces
        /// standards. 
        /// 
        private bool IsIgnorableAttribute() 
        { 
            string ns = _reader.NamespaceURI;
            return ns == XmlNamespace || ns == XmlnsNamespace; 
        }

        #region error reporting
 
        /// 
        /// Make sure the minimum required information is specified. 
        ///  
        private void VerifyCompositeFontInfo()
        { 
            if (_compositeFontInfo.FamilyMaps.Count == 0)
                Fail(SR.Get(SRID.CompositeFontMissingElement, FamilyMapElement));

            if (_compositeFontInfo.FamilyNames.Count == 0) 
                Fail(SR.Get(SRID.CompositeFontMissingElement, StringElement));
        } 
 
        /// 
        /// Fail because of an XML exception. 
        /// 
        private void FailNotWellFormed(Exception x)
        {
            throw new FileFormatException(new Uri(_reader.BaseURI, UriKind.RelativeOrAbsolute), x); 
        }
 
        ///  
        /// Fail because of an incorrect attribute value.
        ///  
        private void FailAttributeValue()
        {
            Fail(SR.Get(
                SRID.CompositeFontAttributeValue1, 
                _reader.LocalName));
        } 
 
        /// 
        /// Fail because of an incorrect attribute value with an inner exception. 
        /// 
        private void FailAttributeValue(Exception x)
        {
            Fail(SR.Get( 
                SRID.CompositeFontAttributeValue2,
                _reader.LocalName, 
                x.Message), 
                x);
        } 

        /// 
        /// Fail because of an unknown element.
        ///  
        private void FailUnknownElement()
        { 
            Fail(SR.Get( 
                SRID.CompositeFontUnknownElement,
                _reader.LocalName, 
                _reader.NamespaceURI));
        }

        ///  
        /// Fail because of an unknown attribute.
        ///  
        private void FailUnknownAttribute() 
        {
            Fail(SR.Get( 
                SRID.CompositeFontUnknownAttribute,
                _reader.LocalName,
                _reader.NamespaceURI));
        } 

        ///  
        /// Fail because a required attribute is not present. 
        /// 
        ///  
        private void FailMissingAttribute(string name)
        {
            Fail(SR.Get(SRID.CompositeFontMissingAttribute, name));
        } 

        ///  
        ///  Fail with a specified error message. 
        /// 
        private void Fail(string message) 
        {
            Fail(message, null);
        }
 
        /// 
        /// Fail with a specified error message and inner exception. 
        ///  
        private void Fail(string message, Exception innerException)
        { 
            string fileName = _reader.BaseURI;
            throw new FileFormatException(new Uri(fileName, UriKind.RelativeOrAbsolute), message, innerException);
        }
        #endregion 

        private CompositeFontInfo _compositeFontInfo; 
 
        private XmlReader _reader;
 
        // XML namespaces for which Mapping processing instructions have been read. For each entry,
        // the key is the XML namespace, and the value is either SystemClrNamespace (if the the
        // Mapping PI specifies "System" and "MSCORLIB") or String.Empty (any other Mapping).
        private Hashtable _namespaceMap; 

        // Type converters for double and XmlLanguage types. 
        private CultureInfo _englishUSCulture; 
        private TypeConverter _doubleTypeConverter;
        private TypeConverter _xmlLanguageTypeConverter; 

        private const string SystemClrNamespace = "System";

        private const string CompositeFontNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/composite-font"; 
        private const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
        private const string XmlNamespace = "http://www.w3.org/XML/1998/namespace"; 
        private const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/"; 

        private const string FontFamilyElement = "FontFamily"; 
        private const string BaselineAttribute = "Baseline";
        private const string LineSpacingAttribute = "LineSpacing";
        private const string FamilyNamesPropertyElement = "FontFamily.FamilyNames";
        private const string StringElement = "String"; 
        private const string FamilyTypefacesPropertyElement = "FontFamily.FamilyTypefaces";
        private const string FamilyTypefaceElement = "FamilyTypeface"; 
        private const string FamilyMapsPropertyElement = "FontFamily.FamilyMaps"; 
        private const string FamilyMapElement = "FontFamilyMap";
        private const string KeyAttribute = "Key"; 
        private const string LanguageAttribute = "Language";
        private const string NameAttribute = "Name";
        private const string StyleAttribute = "Style";
        private const string WeightAttribute = "Weight"; 
        private const string StretchAttribute = "Stretch";
        private const string UnderlinePositionAttribute = "UnderlinePosition"; 
        private const string UnderlineThicknessAttribute = "UnderlineThickness"; 
        private const string StrikethroughPositionAttribute = "StrikethroughPosition";
        private const string StrikethroughThicknessAttribute = "StrikethroughThickness"; 
        private const string CapsHeightAttribute = "CapsHeight";
        private const string XHeightAttribute = "XHeight";
        private const string UnicodeAttribute = "Unicode";
        private const string TargetAttribute = "Target"; 
        private const string ScaleAttribute = "Scale";
        private const string DeviceFontNameAttribute = "DeviceFontName"; 
        private const string DeviceFontCharacterMetricsPropertyElement = "FamilyTypeface.DeviceFontCharacterMetrics"; 
        private const string CharacterMetricsElement = "CharacterMetrics";
        private const string MetricsAttribute = "Metrics"; 
    }
}

 
namespace MS.Internal.TextFormatting
{ 
    ///  
    /// Partial class splitted from the original one in LineServices.cs.
    /// We do this to avoid bringing in TextFormatting namespace when 
    /// building FontCacheServices.exe
    /// 
    internal static partial class Constants
    { 
        /// 
        /// Greatest multiple of em allowed in composite font file 
        ///  
        public const double GreatestMutiplierOfEm = 100;
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Contents:  The XML Composite font parsing 
//
// Created:   6-11-2003 Tarek Mahmoud Sayed ([....]) 
// 
//---------------------------------------------------------------------------
 
using System;
using System.IO;
using System.Security;
using System.Security.Permissions; 
using System.Text;
using System.Windows; 
using System.Windows.Media; 
using System.Windows.Markup;
using System.Xml; 
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 
using MS.Internal.TextFormatting;
 
using System.Reflection; 

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;

namespace MS.Internal.FontFace
{ 
    internal class CompositeFontParser
    { 
        internal static void VerifyMultiplierOfEm(string propertyName, ref double value) 
        {
            if (DoubleUtil.IsNaN(value)) 
            {
                throw new ArgumentException(SR.Get(SRID.PropertyValueCannotBeNaN, propertyName));
            }
            else if (value > Constants.GreatestMutiplierOfEm) 
            {
                value = Constants.GreatestMutiplierOfEm; 
            } 
            else if (value < -Constants.GreatestMutiplierOfEm)
            { 
                value = -Constants.GreatestMutiplierOfEm;
            }
        }
 
        internal static void VerifyPositiveMultiplierOfEm(string propertyName, ref double value)
        { 
            if (DoubleUtil.IsNaN(value)) 
            {
                throw new ArgumentException(SR.Get(SRID.PropertyValueCannotBeNaN, propertyName)); 
            }
            else if (value > Constants.GreatestMutiplierOfEm)
            {
                value = Constants.GreatestMutiplierOfEm; 
            }
            else if (value <= 0) 
            { 
                throw new ArgumentException(SR.Get(SRID.PropertyMustBeGreaterThanZero, propertyName));
            } 
        }

        internal static void VerifyNonNegativeMultiplierOfEm(string propertyName, ref double value)
        { 
            if (DoubleUtil.IsNaN(value))
            { 
                throw new ArgumentException(SR.Get(SRID.PropertyValueCannotBeNaN, propertyName)); 
            }
            else if (value > Constants.GreatestMutiplierOfEm) 
            {
                value = Constants.GreatestMutiplierOfEm;
            }
            else if (value < 0) 
            {
                throw new ArgumentException(SR.Get(SRID.PropertyCannotBeNegative, propertyName)); 
            } 
        }
 
        private double GetAttributeAsDouble()
        {
            object value = null;
 
            try
            { 
                value = _doubleTypeConverter.ConvertFromString( 
                    null, // type converter context
                    _englishUSCulture, 
                    GetAttributeValue()
                    );
            }
            catch (NotSupportedException) 
            {
                FailAttributeValue(); 
            } 

            if (value == null) 
                FailAttributeValue();

            return (double)value;
        } 

        private XmlLanguage GetAttributeAsXmlLanguage() 
        { 
            object value = null;
 
            try
            {
                value = _xmlLanguageTypeConverter.ConvertFromString(
                    null, // type converter context 
                    _englishUSCulture,
                    GetAttributeValue() 
                    ); 
            }
            catch (NotSupportedException) 
            {
                FailAttributeValue();
            }
 
            if (value == null)
                FailAttributeValue(); 
 
            return (XmlLanguage)value;
        } 

        /// 
        /// Gets the value of the value of the current node which is assumed to be an
        /// attribute. Checks for markup expressions or escaped braces. 
        /// 
        private string GetAttributeValue() 
        { 
            string s = _reader.Value;
            if (string.IsNullOrEmpty(s)) 
                return string.Empty;

            if (s[0] == '{')
            { 
                if (s.Length > 1 && s[1] == '}')
                { 
                    s = s.Substring(2); 
                }
                else 
                {
                    FailAttributeValue();
                }
            } 

            return s; 
        } 

        private const NumberStyles UnsignedDecimalPointStyle = 
            NumberStyles.AllowTrailingWhite |
            NumberStyles.AllowLeadingWhite  |
            NumberStyles.AllowDecimalPoint;
 
        private const NumberStyles SignedDecimalPointStyle = UnsignedDecimalPointStyle | NumberStyles.AllowLeadingSign;
 
        ///  
        /// Reads the specified composite font file.
        ///  
        internal static CompositeFontInfo LoadXml(Stream fileStream)
        {
            CompositeFontParser parser = new CompositeFontParser(fileStream);
            return parser._compositeFontInfo; 
        }
 
        ///  
        /// Constructs the composite font parser and parses the file.
        ///  
        /// File stream to parse.
        private CompositeFontParser(Stream fileStream)
        {
            _compositeFontInfo = new CompositeFontInfo(); 

            _namespaceMap = new Hashtable(); 
            _englishUSCulture = CultureInfo.GetCultureInfoByIetfLanguageTag("en-US"); 
            _doubleTypeConverter = TypeDescriptor.GetConverter(typeof(double));
            _xmlLanguageTypeConverter = new System.Windows.Markup.XmlLanguageConverter(); 

            _reader = CreateXmlReader(fileStream);

            try 
            {
                if (IsStartElement(FontFamilyElement, CompositeFontNamespace)) 
                { 
                    ParseFontFamilyElement();
                } 
                else
                {
                    FailUnknownElement();
                } 
            }
            catch (XmlException x) 
            { 
                FailNotWellFormed(x);
            } 
            catch (XmlSyntaxException x)
            {
                FailNotWellFormed(x);
            } 
            catch (FormatException x)
            { 
                if (_reader.NodeType == XmlNodeType.Attribute) 
                    FailAttributeValue(x);
                else 
                    Fail(x.Message, x);
            }
            catch (ArgumentException x)
            { 
                if (_reader.NodeType == XmlNodeType.Attribute)
                    FailAttributeValue(x); 
                else 
                    Fail(x.Message, x);
            } 
            finally
            {
                _reader.Close();
                _reader = null; 
            }
        } 
 

        ///  
        /// Creates the XML reader for the specified file.
        /// 
        private XmlReader CreateXmlReader(Stream fileStream)
        { 
            XmlReaderSettings settings = new XmlReaderSettings();
 
            settings.CloseInput = true; 
            settings.IgnoreComments = true;
            settings.IgnoreWhitespace = false; 
            settings.ProhibitDtd = true;

            XmlReader baseReader = XmlReader.Create(fileStream, settings);
 
            return new XmlCompatibilityReader(baseReader, new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported));
        } 
 

        ///  
        /// Determines whether a given XML namespace is "known" (i.e., should always be processed)
        /// or "unknown" (i.e., should be skipped if declared ignorable).
        /// 
        /// XML namespace to look up. 
        /// Other namespace to map to, if any. Used for versioning.
        /// This implementation always returns null in this parameter. 
        ///  
        /// Returns true ("known") for the XAML namespace or the composite font namespace.
        /// for which a Mapping PI exists. 
        /// 
        /// 
        /// System.String is the only object in a mapped namespace that we can instantiate. However,
        /// we don't want to ignore any mapped namespaces for compatibility reasons. In general, it's 
        /// better for us to reject valid XAML than to accept invalid XAML. We therefore don't want
        /// to ignore an element which the XAML parser would not ignore -- the ignored element might 
        /// be invalid. If mapped elements other than System.String are needed in future versions, a 
        /// composite font author can achieve backwards compatibility by conditionalizing mapped
        /// elements using c:AlternateContent markup. 
        /// 
        private bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace)
        {
            newXmlNamespace = null; 
            return xmlNamespace == CompositeFontNamespace ||
                xmlNamespace == XamlNamespace || 
                IsMappedNamespace(xmlNamespace); 
        }
 
        /// 
        /// Calls MoveToContent and checks whether the reader is positioned on the specified element.
        /// 
        ///  
        /// We should always call this method instead of calling _reader.IsStartElement directly because
        /// the latter calls MoveToContent on the underlying reader which means we could fail to parse 
        /// Mapping processing instructions. 
        /// 
        private bool IsStartElement(string localName, string namespaceURI) 
        {
            MoveToContent();
            return _reader.IsStartElement(localName, namespaceURI);
        } 

        ///  
        /// Same semantics as XmlReader.MoveToContent, but this method processes Mapping processing 
        /// instructions as it advances past them.
        ///  
        private XmlNodeType MoveToContent()
        {
            bool contentNode = false;
 
            do
            { 
                switch (_reader.NodeType) 
                {
                    case XmlNodeType.CDATA: 
                    case XmlNodeType.Element:
                    case XmlNodeType.EndElement:
                    case XmlNodeType.EntityReference:
                    case XmlNodeType.EndEntity: 
                        contentNode = true;
                        break; 
                } 
            } while (!contentNode && _reader.Read());
 
            return _reader.NodeType;
        }

        #region ProcessingInstructions 

       private bool IsMappedNamespace(string xmlNamespace) 
        { 
            return _namespaceMap.ContainsKey(xmlNamespace);
        } 

        private bool IsSystemNamespace(string xmlNamespace)
        {
            return (xmlNamespace == "clr-namespace:System;assembly=mscorlib"); 
        }
 
        #endregion ProcessingInstructions 

        ///  
        /// Parses the FontFamily element, including its attributes and children,
        /// and advances to the next sibling element.
        /// 
        private void ParseFontFamilyElement() 
        {
            // Iterate over the attributes. 
            if (_reader.MoveToFirstAttribute()) 
            {
                do 
                {
                    // Process attributes in the composite font namespace
                    if (IsCompositeFontAttribute())
                    { 
                        string name = _reader.LocalName;
 
                        if (name == BaselineAttribute) 
                        {
                            _compositeFontInfo.Baseline = GetAttributeAsDouble(); 
                        }
                        else if (name == LineSpacingAttribute)
                        {
                            _compositeFontInfo.LineSpacing = GetAttributeAsDouble(); 
                        }
                        else 
                        { 
                            FailUnknownAttribute();
                        } 
                    }
                    else if (!IsIgnorableAttribute())
                    {
                        FailUnknownAttribute(); 
                    }
 
                } while (_reader.MoveToNextAttribute()); 

                _reader.MoveToElement(); 
            }

            // Empty element?
            if (_reader.IsEmptyElement) 
            {
                VerifyCompositeFontInfo(); 
                _reader.Read(); 
                return;
            } 

            // Advance past the start tag.
            _reader.Read();
 
            // Iterate over children.
            while (MoveToContent() != XmlNodeType.EndElement) 
            { 
                if (_reader.NodeType == XmlNodeType.Element && _reader.NamespaceURI == CompositeFontNamespace)
                { 
                    bool isEmpty = _reader.IsEmptyElement;

                    // It's an element in the composite font namespace; branch depending on the name.
                    switch (_reader.LocalName) 
                    {
                        case FamilyNamesPropertyElement: 
                            VerifyNoAttributes(); 
                            _reader.Read();
                            if (!isEmpty) 
                            {
                                // Process all child elements.
                                while (MoveToContent() == XmlNodeType.Element)
                                { 
                                    if (_reader.LocalName == StringElement && IsSystemNamespace(_reader.NamespaceURI))
                                    { 
                                        // It's a System.String. 
                                        ParseFamilyNameElement();
                                    } 
                                    else
                                    {
                                        // Only System.String is valid in this context.
                                        FailUnknownElement(); 
                                    }
                                } 
 
                                // Advance past the  end element, or throw
                                // an exception if we're not at an end element. 
                                _reader.ReadEndElement();
                            }
                            break;
 
                        case FamilyTypefacesPropertyElement:
                            VerifyNoAttributes(); 
                            _reader.Read(); 
                            if (!isEmpty)
                            { 
                                // Process child elements, of which the only one we recognize in this
                                // context is FamilyTypeface.
                                while (IsStartElement(FamilyTypefaceElement, CompositeFontNamespace))
                                { 
                                    ParseFamilyTypefaceElement();
                                } 
 
                                // Advance past the  end element, or throw
                                // an exception if we're not at an end element. 
                                _reader.ReadEndElement();
                            }
                            break;
 
                        case FamilyMapsPropertyElement:
                            VerifyNoAttributes(); 
                            _reader.Read(); 
                            if (!isEmpty)
                            { 
                                // Process child elements, of which the only one we recognize in this
                                // context is FontFamilyMap.
                                while (IsStartElement(FamilyMapElement, CompositeFontNamespace))
                                { 
                                    ParseFamilyMapElement();
                                } 
 
                                // Advance past the  end element, or throw
                                // an exception if we're not at an end element. 
                                _reader.ReadEndElement();
                            }
                            break;
 
                        default:
                            // It's some other element. 
                            FailUnknownElement(); 
                            break;
                    } 
                }
                else
                {
                    // It's some other content besides an element in the composite font namespace; skip it. 
                    _reader.Skip();
                } 
            } 

            // We should now have read right up to the  end tag. 
            VerifyCompositeFontInfo();
            _reader.ReadEndElement();
        }
 
        /// 
        /// Makes sure the current element has no attributes (except ignorable ones). 
        ///  
        private void VerifyNoAttributes()
        { 
            if (_reader.MoveToFirstAttribute())
            {
                do
                { 
                    if (!IsIgnorableAttribute())
                        FailUnknownAttribute(); 
 
                } while (_reader.MoveToNextAttribute());
 
                _reader.MoveToElement();
            }
        }
 
        /// 
        /// Parses the FamilyName element (actually String), including its attributes 
        /// and children, and advances to the next sibling element. 
        /// 
        private void ParseFamilyNameElement() 
        {
            XmlLanguage language = null;

            // Iterate over the attributes. 
            if (_reader.MoveToFirstAttribute())
            { 
                do 
                {
                    if (_reader.NamespaceURI == XamlNamespace && _reader.LocalName == KeyAttribute) 
                    {
                        language = GetAttributeAsXmlLanguage();
                    }
                    else if (!IsIgnorableAttribute()) 
                    {
                        FailUnknownAttribute(); 
                    } 

                } while (_reader.MoveToNextAttribute()); 

                _reader.MoveToElement();
            }
 
            // XAML requires x:Key so we should, too.
            if (language == null) 
            { 
                FailMissingAttribute(LanguageAttribute);
            } 

            // The family name is the element content.
            string familyName = _reader.ReadElementString();
            if (string.IsNullOrEmpty(familyName)) 
            {
                FailMissingAttribute(NameAttribute); 
            } 

            _compositeFontInfo.FamilyNames.Add(language, familyName); 
        }

        /// 
        /// Parses the FamilyTypeface element, including its attributes and children, 
        /// and advances to the next sibling element.
        ///  
        private void ParseFamilyTypefaceElement() 
        {
            FamilyTypeface face = new FamilyTypeface(); 

            ParseFamilyTypefaceAttributes(face);

            if (_reader.IsEmptyElement) 
            {
                _reader.Read(); 
            } 
            else
            { 
                _reader.Read();

                while (MoveToContent() != XmlNodeType.EndElement)
                { 
                    if (_reader.NodeType == XmlNodeType.Element && _reader.NamespaceURI == CompositeFontNamespace)
                    { 
                        if (_reader.LocalName == DeviceFontCharacterMetricsPropertyElement) 
                        {
                            VerifyNoAttributes(); 

                            if (_reader.IsEmptyElement)
                            {
                                _reader.Read(); 
                            }
                            else 
                            { 
                                _reader.Read();
 
                                // Process all child elements.
                                while (MoveToContent() == XmlNodeType.Element)
                                {
                                    if (_reader.LocalName == CharacterMetricsElement) 
                                    {
                                        ParseCharacterMetricsElement(face); 
                                    } 
                                    else
                                    { 
                                        // Only CharacterMetricsElement is valid in this context.
                                        FailUnknownElement();
                                    }
                                } 
                                // Process the end element for the collection.
                                _reader.ReadEndElement(); 
                            } 
                        }
                        else 
                        {
                            FailUnknownElement();
                        }
                    } 
                    else
                    { 
                        _reader.Skip(); 
                    }
                } 

                _reader.ReadEndElement();
            }
 
            // Add the typeface.
            _compositeFontInfo.GetFamilyTypefaceList().Add(face); 
        } 

        ///  
        /// Parses the attributes of the FamilyTypeface element and sets the corresponding
        /// properties on the specified FamilyTypeface object. On return, the reader remains
        /// positioned on the element.
        ///  
        private void ParseFamilyTypefaceAttributes(FamilyTypeface face)
        { 
            // Iterate over the attributes. 
            if (_reader.MoveToFirstAttribute())
            { 
                do
                {
                    // Process attributes in the composite font namespace; ignore any others.
                    if (IsCompositeFontAttribute()) 
                    {
                        string name = _reader.LocalName; 
 
                        if (name == StyleAttribute)
                        { 
                            FontStyle fontStyle = new FontStyle();
                            if (!FontStyles.FontStyleStringToKnownStyle(GetAttributeValue(), CultureInfo.InvariantCulture, ref fontStyle))
                                FailAttributeValue();
 
                            face.Style = fontStyle;
                        } 
                        else if (name == WeightAttribute) 
                        {
                            FontWeight fontWeight = new FontWeight(); 
                            if (!FontWeights.FontWeightStringToKnownWeight(GetAttributeValue(), CultureInfo.InvariantCulture, ref fontWeight))
                                FailAttributeValue();

                            face.Weight = fontWeight; 
                        }
                        else if (name == StretchAttribute) 
                        { 
                            FontStretch fontStretch = new FontStretch();
                            if (!FontStretches.FontStretchStringToKnownStretch(GetAttributeValue(), CultureInfo.InvariantCulture, ref fontStretch)) 
                                FailAttributeValue();

                            face.Stretch = fontStretch;
                        } 
                        else if (name == UnderlinePositionAttribute)
                        { 
                            face.UnderlinePosition = GetAttributeAsDouble(); 
                        }
                        else if (name == UnderlineThicknessAttribute) 
                        {
                            face.UnderlineThickness = GetAttributeAsDouble();
                        }
                        else if (name == StrikethroughPositionAttribute) 
                        {
                            face.StrikethroughPosition = GetAttributeAsDouble(); 
                        } 
                        else if (name == StrikethroughThicknessAttribute)
                        { 
                            face.StrikethroughThickness = GetAttributeAsDouble();
                        }
                        else if (name == CapsHeightAttribute)
                        { 
                            face.CapsHeight = GetAttributeAsDouble();
                        } 
                        else if (name == XHeightAttribute) 
                        {
                            face.XHeight = GetAttributeAsDouble(); 
                        }
                        else if (name == DeviceFontNameAttribute)
                        {
                            face.DeviceFontName = GetAttributeValue(); 
                        }
                        else 
                        { 
                            FailUnknownAttribute();
                        } 
                    }
                    else if (!IsIgnorableAttribute())
                    {
                        FailUnknownAttribute(); 
                    }
 
                } while (_reader.MoveToNextAttribute()); 

                _reader.MoveToElement(); 
            }
        }

        ///  
        /// Parses a CharacterMetrics element, and advances the current position beyond the
        /// element. Adds a CharacterMetrics object to the given FamilyTypface. 
        ///  
        private void ParseCharacterMetricsElement(FamilyTypeface face)
        { 
            string key = null;
            string metrics = null;

            if (_reader.MoveToFirstAttribute()) 
            {
                do 
                { 
                    if (_reader.NamespaceURI == XamlNamespace && _reader.LocalName == KeyAttribute)
                    { 
                        key = GetAttributeValue();
                    }
                    else if (IsCompositeFontAttribute() && _reader.LocalName == MetricsAttribute)
                    { 
                        metrics = GetAttributeValue();
                    } 
                    else if (!IsIgnorableAttribute()) 
                    {
                        FailUnknownAttribute(); 
                    }
                } while (_reader.MoveToNextAttribute());

                _reader.MoveToElement(); 
            }
 
            if (key == null) 
                FailMissingAttribute(KeyAttribute);
 
            if (metrics == null)
                FailMissingAttribute(MetricsAttribute);

            face.DeviceFontCharacterMetrics.Add( 
                CharacterMetricsDictionary.ConvertKey(key),
                new CharacterMetrics(metrics) 
                ); 

            // There should be no child elements. 
            ParseEmptyElement();
        }

        ///  
        /// Parses the FontFamilyMap element, including its attributes and children,
        /// and advances to the next sibling element. 
        ///  
        private void ParseFamilyMapElement()
        { 
            FontFamilyMap fmap = new FontFamilyMap();

            // Parse the family map attributes.
            if (_reader.MoveToFirstAttribute()) 
            {
                do 
                { 
                    // Process attributes in the composite font namespace; ignore any others.
                    if (IsCompositeFontAttribute()) 
                    {
                        string name = _reader.LocalName;

                        if (name == UnicodeAttribute) 
                        {
                            fmap.Unicode = GetAttributeValue(); 
                        } 
                        else if (name == TargetAttribute)
                        { 
                            fmap.Target = GetAttributeValue();
                        }
                        else if (name == ScaleAttribute)
                        { 
                            fmap.Scale = GetAttributeAsDouble();
                        } 
                        else if (name == LanguageAttribute) 
                        {
                            fmap.Language = GetAttributeAsXmlLanguage(); 
                        }
                        else
                        {
                            FailUnknownAttribute(); 
                        }
                    } 
                    else if (!IsIgnorableAttribute()) 
                    {
                        FailUnknownAttribute(); 
                    }

                } while (_reader.MoveToNextAttribute());
 
                _reader.MoveToElement();
            } 
 
            _compositeFontInfo.FamilyMaps.Add(fmap);
 
            // There should be no child elements.
            ParseEmptyElement();
        }
 
        /// 
        /// Advances past the current element and its children, throwing and exception 
        /// if there are any child elements in the composite font namespace. 
        /// 
        private void ParseEmptyElement() 
        {
            if (_reader.IsEmptyElement)
            {
                _reader.Read(); 
                return;
            } 
 
            _reader.Read();
 
            while (MoveToContent() != XmlNodeType.EndElement)
            {
                if (_reader.NodeType == XmlNodeType.Element && _reader.NamespaceURI == CompositeFontNamespace)
                { 
                    FailUnknownElement();
                } 
                else 
                {
                    _reader.Skip(); 
                }
            }

            _reader.ReadEndElement(); 
        }
 
        ///  
        /// Determines whether the reader is positioned on an composite font attribute,
        /// which we define to me either (a) it has no namespace at all, or (b) it's in 
        /// the composite font namespace.
        /// 
        private bool IsCompositeFontAttribute()
        { 
            string ns = _reader.NamespaceURI;
            return string.IsNullOrEmpty(ns) || ns == CompositeFontNamespace; 
        } 

        ///  
        /// Determines whether the attribute can be safely ignored, even if it
        /// has not been explicitly declared as ignorable via compatibility markup.
        /// Currently, we ignore attributes defined by the XML and XML namespaces
        /// standards. 
        /// 
        private bool IsIgnorableAttribute() 
        { 
            string ns = _reader.NamespaceURI;
            return ns == XmlNamespace || ns == XmlnsNamespace; 
        }

        #region error reporting
 
        /// 
        /// Make sure the minimum required information is specified. 
        ///  
        private void VerifyCompositeFontInfo()
        { 
            if (_compositeFontInfo.FamilyMaps.Count == 0)
                Fail(SR.Get(SRID.CompositeFontMissingElement, FamilyMapElement));

            if (_compositeFontInfo.FamilyNames.Count == 0) 
                Fail(SR.Get(SRID.CompositeFontMissingElement, StringElement));
        } 
 
        /// 
        /// Fail because of an XML exception. 
        /// 
        private void FailNotWellFormed(Exception x)
        {
            throw new FileFormatException(new Uri(_reader.BaseURI, UriKind.RelativeOrAbsolute), x); 
        }
 
        ///  
        /// Fail because of an incorrect attribute value.
        ///  
        private void FailAttributeValue()
        {
            Fail(SR.Get(
                SRID.CompositeFontAttributeValue1, 
                _reader.LocalName));
        } 
 
        /// 
        /// Fail because of an incorrect attribute value with an inner exception. 
        /// 
        private void FailAttributeValue(Exception x)
        {
            Fail(SR.Get( 
                SRID.CompositeFontAttributeValue2,
                _reader.LocalName, 
                x.Message), 
                x);
        } 

        /// 
        /// Fail because of an unknown element.
        ///  
        private void FailUnknownElement()
        { 
            Fail(SR.Get( 
                SRID.CompositeFontUnknownElement,
                _reader.LocalName, 
                _reader.NamespaceURI));
        }

        ///  
        /// Fail because of an unknown attribute.
        ///  
        private void FailUnknownAttribute() 
        {
            Fail(SR.Get( 
                SRID.CompositeFontUnknownAttribute,
                _reader.LocalName,
                _reader.NamespaceURI));
        } 

        ///  
        /// Fail because a required attribute is not present. 
        /// 
        ///  
        private void FailMissingAttribute(string name)
        {
            Fail(SR.Get(SRID.CompositeFontMissingAttribute, name));
        } 

        ///  
        ///  Fail with a specified error message. 
        /// 
        private void Fail(string message) 
        {
            Fail(message, null);
        }
 
        /// 
        /// Fail with a specified error message and inner exception. 
        ///  
        private void Fail(string message, Exception innerException)
        { 
            string fileName = _reader.BaseURI;
            throw new FileFormatException(new Uri(fileName, UriKind.RelativeOrAbsolute), message, innerException);
        }
        #endregion 

        private CompositeFontInfo _compositeFontInfo; 
 
        private XmlReader _reader;
 
        // XML namespaces for which Mapping processing instructions have been read. For each entry,
        // the key is the XML namespace, and the value is either SystemClrNamespace (if the the
        // Mapping PI specifies "System" and "MSCORLIB") or String.Empty (any other Mapping).
        private Hashtable _namespaceMap; 

        // Type converters for double and XmlLanguage types. 
        private CultureInfo _englishUSCulture; 
        private TypeConverter _doubleTypeConverter;
        private TypeConverter _xmlLanguageTypeConverter; 

        private const string SystemClrNamespace = "System";

        private const string CompositeFontNamespace = "http://schemas.microsoft.com/winfx/2006/xaml/composite-font"; 
        private const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
        private const string XmlNamespace = "http://www.w3.org/XML/1998/namespace"; 
        private const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/"; 

        private const string FontFamilyElement = "FontFamily"; 
        private const string BaselineAttribute = "Baseline";
        private const string LineSpacingAttribute = "LineSpacing";
        private const string FamilyNamesPropertyElement = "FontFamily.FamilyNames";
        private const string StringElement = "String"; 
        private const string FamilyTypefacesPropertyElement = "FontFamily.FamilyTypefaces";
        private const string FamilyTypefaceElement = "FamilyTypeface"; 
        private const string FamilyMapsPropertyElement = "FontFamily.FamilyMaps"; 
        private const string FamilyMapElement = "FontFamilyMap";
        private const string KeyAttribute = "Key"; 
        private const string LanguageAttribute = "Language";
        private const string NameAttribute = "Name";
        private const string StyleAttribute = "Style";
        private const string WeightAttribute = "Weight"; 
        private const string StretchAttribute = "Stretch";
        private const string UnderlinePositionAttribute = "UnderlinePosition"; 
        private const string UnderlineThicknessAttribute = "UnderlineThickness"; 
        private const string StrikethroughPositionAttribute = "StrikethroughPosition";
        private const string StrikethroughThicknessAttribute = "StrikethroughThickness"; 
        private const string CapsHeightAttribute = "CapsHeight";
        private const string XHeightAttribute = "XHeight";
        private const string UnicodeAttribute = "Unicode";
        private const string TargetAttribute = "Target"; 
        private const string ScaleAttribute = "Scale";
        private const string DeviceFontNameAttribute = "DeviceFontName"; 
        private const string DeviceFontCharacterMetricsPropertyElement = "FamilyTypeface.DeviceFontCharacterMetrics"; 
        private const string CharacterMetricsElement = "CharacterMetrics";
        private const string MetricsAttribute = "Metrics"; 
    }
}

 
namespace MS.Internal.TextFormatting
{ 
    ///  
    /// Partial class splitted from the original one in LineServices.cs.
    /// We do this to avoid bringing in TextFormatting namespace when 
    /// building FontCacheServices.exe
    /// 
    internal static partial class Constants
    { 
        /// 
        /// Greatest multiple of em allowed in composite font file 
        ///  
        public const double GreatestMutiplierOfEm = 100;
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK