File: Core\CSharp\MS\Internal\FontFace\TypefaceCollection.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//-----------------------------------------------------------------------
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2002
//
//  File:      TypefaceCollection.cs
//
//  Contents:  Collection of typefaces
//
//  Created:   5-15-2003 Michael Leonov (mleonov)
//
//------------------------------------------------------------------------
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using MS.Internal.FontCache;
using System.Globalization;
using System.Security;
 
using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
 
namespace MS.Internal.FontFace
{
    internal unsafe struct TypefaceCollection : ICollection<Typeface>
    {
        private FontFamily                    _fontFamily;
 
        // setting _family and _familyTypefaceCollection are mutually exclusive.
        private Text.TextInterface.FontFamily _family;
        private FamilyTypefaceCollection      _familyTypefaceCollection;
 
        public TypefaceCollection(FontFamily fontFamily, Text.TextInterface.FontFamily family)
        {
            _fontFamily = fontFamily;
            _family = family;
            _familyTypefaceCollection = null;
        }
 
        public TypefaceCollection(FontFamily fontFamily, FamilyTypefaceCollection familyTypefaceCollection)
        {
            _fontFamily = fontFamily;
            _familyTypefaceCollection = familyTypefaceCollection;
            _family = null;
        }
 
        #region ICollection<Typeface> Members
 
        public void Add(Typeface item)
        {
            throw new NotSupportedException();
        }
 
        public void Clear()
        {
            throw new NotSupportedException();
        }
 
        public bool Contains(Typeface item)
        {
            foreach (Typeface t in this)
            {
                if (t.Equals(item))
                    return true;
            }
            return false;
        }
 
        public void CopyTo(Typeface[] array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }
 
            if (array.Rank != 1)
            {
                throw new ArgumentException(SR.Get(SRID.Collection_BadRank));
            }
 
            // The extra "arrayIndex >= array.Length" check in because even if _collection.Count
            // is 0 the index is not allowed to be equal or greater than the length
            // (from the MSDN ICollection docs)
            if (arrayIndex < 0 || arrayIndex >= array.Length || (arrayIndex + Count) > array.Length)
            {
                throw new ArgumentOutOfRangeException("arrayIndex");
            }
 
            foreach (Typeface t in this)
            {
                array[arrayIndex++] = t;
            }
        }
 
        /// <SecurityNote>
        /// Critical - calls into critical Text.TextInterface.FontFamily property
        /// TreatAsSafe - Count is safe to expose
        /// </SecurityNote>
        public int Count
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                Debug.Assert((_family != null && _familyTypefaceCollection == null)|| (_familyTypefaceCollection != null && _family == null));
                if (_family != null)
                {
                    return checked((int)_family.Count);
                }
                else
                {
                    return _familyTypefaceCollection.Count;
                }
            }
        }
 
        public bool IsReadOnly
        {
            get
            {
                return true;
            }
        }
 
        public bool Remove(Typeface item)
        {
            throw new NotSupportedException();
        }
 
        #endregion
 
        #region IEnumerable<Typeface> Members
 
        public IEnumerator<Typeface> GetEnumerator()
        {
            return new Enumerator(this);
        }
 
        #endregion
 
        #region IEnumerable Members
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }
 
        #endregion
 
        private struct Enumerator : IEnumerator<Typeface>
        {
            public Enumerator(TypefaceCollection typefaceCollection)
            {
                _typefaceCollection = typefaceCollection;
 
                Debug.Assert((typefaceCollection._family != null && typefaceCollection._familyTypefaceCollection == null)
                    || (typefaceCollection._familyTypefaceCollection != null && typefaceCollection._family == null));
                if (typefaceCollection._family != null)
                {
                    _familyEnumerator = ((IEnumerable<Text.TextInterface.Font>)typefaceCollection._family).GetEnumerator();
                    _familyTypefaceEnumerator = null;
                }
                else
                {
                    _familyTypefaceEnumerator = ((IEnumerable<FamilyTypeface>)typefaceCollection._familyTypefaceCollection).GetEnumerator();
                    _familyEnumerator = null;
                }
            }
 
            #region IEnumerator<Typeface> Members
 
            /// <SecurityNote>
            /// Critical - calls into critical Text.TextInterface.Font properties
            /// TreatAsSafe - data used to initialize the new Typeface is safe to expose
            /// </SecurityNote>
            public Typeface Current
            {
                [SecurityCritical, SecurityTreatAsSafe]
                get
                {
                    if (_typefaceCollection._family != null)
                    {
                        Text.TextInterface.Font face = _familyEnumerator.Current;
                        return new Typeface(_typefaceCollection._fontFamily, new FontStyle((int)face.Style), new FontWeight((int)face.Weight), new FontStretch((int)face.Stretch));
                    }
                    else
                    {
                        FamilyTypeface familyTypeface = _familyTypefaceEnumerator.Current;
                        return new Typeface(_typefaceCollection._fontFamily, familyTypeface.Style, familyTypeface.Weight, familyTypeface.Stretch);
                    }
                }
            }
 
            #endregion
 
            #region IDisposable Members
 
            public void Dispose() {}
 
            #endregion
 
            #region IEnumerator Members
 
            object System.Collections.IEnumerator.Current
            {
                get
                {
                    return ((IEnumerator<Typeface>)this).Current;
                }
            }
 
            public bool MoveNext()
            {
                if (_familyEnumerator != null)
                {
                    return _familyEnumerator.MoveNext();
                }
                else
                {
                    return _familyTypefaceEnumerator.MoveNext();
                }
            }
 
            public void Reset()
            {
                if (_typefaceCollection._family != null)
                {
                    _familyEnumerator = ((IEnumerable<Text.TextInterface.Font>)_typefaceCollection._family).GetEnumerator();
                    _familyTypefaceEnumerator = null;
                }
                else
                {
                    _familyTypefaceEnumerator = ((IEnumerable<FamilyTypeface>)_typefaceCollection._familyTypefaceCollection).GetEnumerator();
                    _familyEnumerator = null;
                }
            }
 
            #endregion
 
            // setting _familyEnumerator and _familyTypefaceEnumerator are mutually exclusive.
            private IEnumerator<Text.TextInterface.Font> _familyEnumerator;
            private IEnumerator<FamilyTypeface>          _familyTypefaceEnumerator;
            private TypefaceCollection                   _typefaceCollection;
        }
    }
}