CharacterMetricsDictionary.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / CharacterMetricsDictionary.cs / 1305600 / CharacterMetricsDictionary.cs

                            //------------------------------------------------------------------------ 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2002
// 
//  File:      CharacterMetricsDictionary.cs
// 
//  Contents:  CharacterMetricsDictionary 
//
//  Created:   6-6-05 Niklas Borson (niklasb) 
//
//-----------------------------------------------------------------------

using System; 
using SC=System.Collections;
using System.Collections.Generic; 
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 

// Allow suppression of presharp warnings
#pragma warning disable 1634, 1691
 
namespace System.Windows.Media
{ 
    ///  
    /// Dictionary of character metrics for a device font indexed by Unicode scalar value.
    ///  
    public sealed class CharacterMetricsDictionary : IDictionary, SC.IDictionary
    {
        /// 
        /// Constructs an empty CharacterMetricsDictionary object. 
        /// 
        internal CharacterMetricsDictionary() 
        { 
        }
 
        #region IEnumerable members

        /// 
        /// Returns an enumerator that iterates through the collection. 
        /// 
        [CLSCompliant(false)] 
        public IEnumerator> GetEnumerator() 
        {
            return new Enumerator(this); 
        }

        SC.IEnumerator SC.IEnumerable.GetEnumerator()
        { 
            return new Enumerator(this);
        } 
 
        SC.IDictionaryEnumerator SC.IDictionary.GetEnumerator()
        { 
            return new Enumerator(this);
        }

        ///  
        /// If the dictionary contains an entry for the specified character code, returns true
        /// and stores the CharacterMetrics in the value parameter; otherwise returns false and 
        /// sets value to null. 
        /// 
        public bool TryGetValue(int key, out CharacterMetrics value) 
        {
            value = GetValue(key);
            return value != null;
        } 

        #endregion 
 
        #region ICollection members
 
        /// 
        /// Gets the number of objects in the collection.
        /// 
        public int Count 
        {
            get 
            { 
                if (_count == 0)
                { 
                    _count = CountValues();
                }
                return _count;
            } 
        }
 
        ///  
        /// Gets a value indicating whether the collection is read-only.
        ///  
        public bool IsReadOnly
        {
            get { return false; }
        } 

        ///  
        /// Adds a character code and associated CharacterMetrics to the collection. 
        /// 
        [CLSCompliant(false)] 
        public void Add(KeyValuePair item)
        {
            SetValue(
                item.Key, 
                item.Value,
                true // failIfExists 
                ); 
        }
 
        /// 
        /// Removes all objects from the collection.
        /// 
        public void Clear() 
        {
            _count = 0; 
            _pageTable = null; 
        }
 
        /// 
        /// Determines whether the collection contains the specified characterCode-CharacterMetrics pair.
        /// 
        [CLSCompliant(false)] 
        public bool Contains(KeyValuePair item)
        { 
            // Suppress PRESharp warning that item.Value can be null; apparently PRESharp 
            // doesn't understand short circuit evaluation of operator &&.
#pragma warning suppress 56506 
            return item.Value != null && item.Value.Equals(GetValue(item.Key));
        }

        ///  
        /// Copies the contents of the collection to the specified array.
        ///  
        [CLSCompliant(false)] 
        public void CopyTo(KeyValuePair[] array, int index)
        { 
            if (array == null)
                throw new ArgumentNullException("array");

            if (index < 0) 
                throw new ArgumentOutOfRangeException("index");
 
            if (index >= array.Length) 
                throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_IndexGreaterThanOrEqualToArrayLength, "index", "array"));
 
            CharacterMetrics[][] pageTable = _pageTable;
            if (pageTable != null)
            {
                int k = index; 

                for (int i = 0; i < pageTable.Length; ++i) 
                { 
                    CharacterMetrics[] page = pageTable[i];
                    if (page != null) 
                    {
                        for (int j = 0; j < page.Length; ++j)
                        {
                            CharacterMetrics metrics = page[j]; 
                            if (metrics != null)
                            { 
                                if (k >= array.Length) 
                                    throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_NumberOfElementsExceedsArrayLength, index, "array"));
 
                                array[k++] = new KeyValuePair(
                                    (i << PageShift) | j,
                                    metrics
                                    ); 
                            }
                        } 
                    } 
                }
            } 
        }

        /// 
        /// Removes the specified characterCode-CharacterMetrics pair from the collection. 
        /// 
        [CLSCompliant(false)] 
        public bool Remove(KeyValuePair item) 
        {
            return item.Value != null && RemoveValue(item.Key, item.Value); 
        }

        bool SC.ICollection.IsSynchronized
        { 
            get { return false; }
        } 
 
        object SC.ICollection.SyncRoot
        { 
            get { return this; }
        }

        void SC.ICollection.CopyTo(Array array, int index) 
        {
            if (array == null) 
                throw new ArgumentNullException("array"); 

            if (index < 0) 
                throw new ArgumentOutOfRangeException("index");

            if (index >= array.Length)
                throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_IndexGreaterThanOrEqualToArrayLength, "index", "array")); 

            if (Count > array.Length - index) 
                throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_NumberOfElementsExceedsArrayLength, index, "array")); 

            SC.DictionaryEntry[] typedArray = array as SC.DictionaryEntry[]; 
            if (typedArray != null)
            {
                // it's an array of the exact type
                foreach (KeyValuePair item in this) 
                {
                    typedArray[index++] = new SC.DictionaryEntry(item.Key, item.Value); 
                } 
            }
            else 
            {
                // it's an array of some other type, e.g., object[]; make sure it's one dimensional
                if (array.Rank != 1)
                    throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_ArrayCannotBeMultidimensional)); 

                // make sure the element type is compatible 
                Type elementType = array.GetType().GetElementType(); 
                if (!elementType.IsAssignableFrom(typeof(SC.DictionaryEntry)))
                    throw new ArgumentException(SR.Get(SRID.CannotConvertType, typeof(SC.DictionaryEntry), elementType)); 

                foreach (KeyValuePair item in this)
                {
                    array.SetValue(new SC.DictionaryEntry(item.Key, item.Value), index++); 
                }
            } 
        } 

        #endregion 

        #region IDictionary members

        ///  
        /// Adds a character code and associated CharacterMetrics to the collection.
        ///  
        public void Add(int key, CharacterMetrics value) 
        {
            SetValue(key, value, /* failIfExists = */ true); 
        }

        /// 
        /// Determines whether the collection contains the specified character code. 
        /// 
        public bool ContainsKey(int key) 
        { 
            return GetValue(key) != null;
        } 

        /// 
        /// Removes the specified character code and associated CharacterMetrics.
        ///  
        public bool Remove(int key)
        { 
            return RemoveValue(key, null); 
        }
 
        /// 
        /// Gets or sets the CharacterMetrics associated with the specified character code.
        /// 
        public CharacterMetrics this[int key] 
        {
            get { return GetValue(key); } 
            set { SetValue(key, value, /* failIfExists = */ false); } 
        }
 
        /// 
        /// Gets a collection containing the keys (character codes) in the dictionary.
        /// 
        [CLSCompliant(false)] 
        public ICollection Keys
        { 
            get { return GetKeys(); } 
        }
 
        /// 
        /// Gets a collection containing the values (strings) in the dictionary.
        /// 
        [CLSCompliant(false)] 
        public ICollection Values
        { 
            get { return GetValues(); } 
        }
 
        bool SC.IDictionary.IsFixedSize
        {
            get { return false; }
        } 

        object SC.IDictionary.this[object key] 
        { 
            get
            { 
                return (key is int) ? GetValue((int)key) : null;
            }

            set 
            {
                SetValue(ConvertKey(key), ConvertValue(value), /* failIfExists = */ false); 
            } 
        }
 
        SC.ICollection SC.IDictionary.Keys
        {
            get { return GetKeys(); }
        } 

        SC.ICollection SC.IDictionary.Values 
        { 
            get { return GetValues(); }
        } 

        void SC.IDictionary.Add(object key, object value)
        {
            SetValue(ConvertKey(key), ConvertValue(value), /* failIfExists = */ false); 
        }
 
        bool SC.IDictionary.Contains(object key) 
        {
            return key is int && GetValue((int)key) != null; 
        }

        void SC.IDictionary.Remove(object key)
        { 
            if (key is int)
            { 
                RemoveValue((int)key, null); 
            }
        } 
        #endregion

        #region Internal representation
 
        internal const int LastDeviceFontCharacterCode = 0xFFFF;
 
        internal const int PageShift = 8; 
        internal const int PageSize = 1 << PageShift;
        internal const int PageMask = PageSize - 1; 
        internal const int PageCount = (LastDeviceFontCharacterCode + 1 + (PageSize - 1)) / PageSize;

        private CharacterMetrics[][] _pageTable = null;
        private int _count = 0; 

        internal CharacterMetrics[] GetPage(int i) 
        { 
            return (_pageTable != null) ? _pageTable[i] : null;
        } 

        private CharacterMetrics[] GetPageFromUnicodeScalar(int unicodeScalar)
        {
            int i = unicodeScalar >> PageShift; 

            CharacterMetrics[] page; 
 
            if (_pageTable != null)
            { 
                page = _pageTable[i];
                if (page == null)
                {
                    _pageTable[i] = page = new CharacterMetrics[PageSize]; 
                }
            } 
            else 
            {
                _pageTable = new CharacterMetrics[PageCount][]; 
                _pageTable[i] = page = new CharacterMetrics[PageSize];
            }

            return page; 
        }
 
        private void SetValue(int key, CharacterMetrics value, bool failIfExists) 
        {
            if (key < 0 || key > LastDeviceFontCharacterCode) 
                throw new ArgumentOutOfRangeException(SR.Get(SRID.CodePointOutOfRange, key));

            if (value == null)
                throw new ArgumentNullException("value"); 

            CharacterMetrics[] page = GetPageFromUnicodeScalar(key); 
            int i = key & PageMask; 

            if (failIfExists && page[i] != null) 
                throw new ArgumentException(SR.Get(SRID.CollectionDuplicateKey, key));

            page[i] = value;
            _count = 0; 
        }
 
        internal CharacterMetrics GetValue(int key) 
        {
            CharacterMetrics metrics = null; 

            if (key >= 0 && key <= FontFamilyMap.LastUnicodeScalar && _pageTable != null)
            {
                CharacterMetrics[] page = _pageTable[key >> PageShift]; 
                if (page != null)
                    metrics = page[key & PageMask]; 
            } 

            return metrics; 
        }

        private bool RemoveValue(int key, CharacterMetrics value)
        { 
            if (key >= 0 && key <= FontFamilyMap.LastUnicodeScalar && _pageTable != null)
            { 
                CharacterMetrics[] page = _pageTable[key >> PageShift]; 
                if (page != null)
                { 
                    int i = key & PageMask;
                    CharacterMetrics metrics = page[i];

                    if (metrics != null && (value == null || metrics.Equals(value))) 
                    {
                        page[i] = null; 
                        _count = 0; 
                        return true;
                    } 
                }
            }
            return false;
        } 

        private CharacterMetrics GetNextValue(ref int unicodeScalar) 
        { 
            CharacterMetrics[][] pageTable = _pageTable;
            if (pageTable != null) 
            {
                int j = (unicodeScalar + 1) & PageMask;

                for (int i = (unicodeScalar + 1) >> PageShift; i < PageCount; ++i) 
                {
                    CharacterMetrics[] page = pageTable[i]; 
                    if (page != null) 
                    {
                        for (; j < PageSize; ++j) 
                        {
                            CharacterMetrics metrics = page[j];
                            if (metrics != null)
                            { 
                                unicodeScalar = (i << PageShift) | j;
                                return metrics; 
                            } 
                        }
 
                        j = 0;
                    }
                }
            } 

            unicodeScalar = int.MaxValue; 
            return null; 
        }
 
        private int CountValues()
        {
            int c = 0;
 
            CharacterMetrics[][] pageTable = _pageTable;
            if (pageTable != null) 
            { 
                for (int i = 0; i < pageTable.Length; ++i)
                { 
                    CharacterMetrics[] page = pageTable[i];
                    if (page != null)
                    {
                        for (int j = 0; j < page.Length; ++j) 
                        {
                            if (page[j] != null) 
                                ++c; 
                        }
                    } 
                }
            }

            return c; 
        }
 
        private int[] GetKeys() 
        {
            int[] result = new int[Count]; 
            int i = 0;
            foreach (KeyValuePair pair in this)
            {
                result[i++] = pair.Key; 
            }
            return result; 
        } 

        private CharacterMetrics[] GetValues() 
        {
            CharacterMetrics[] result = new CharacterMetrics[Count];
            int i = 0;
            foreach (KeyValuePair pair in this) 
            {
                result[i++] = pair.Value; 
            } 
            return result;
        } 

        internal static int ConvertKey(object key)
        {
            if (key == null) 
                throw new ArgumentNullException("key");
 
            int value; 

            string s = key as string; 
            if (s != null)
            {
                int i = 0;
                if (!FontFamilyMap.ParseHexNumber(s, ref i, out value) || i < s.Length) 
                    throw new ArgumentException(SR.Get(SRID.CannotConvertStringToType, s, "int"), "key");
            } 
            else if (key is int) 
            {
                value = (int)key; 
            }
            else
            {
                throw new ArgumentException(SR.Get(SRID.CannotConvertType, key.GetType(), "int"), "key"); 
            }
 
            if (value < 0 || value > FontFamilyMap.LastUnicodeScalar) 
                throw new ArgumentException(SR.Get(SRID.CodePointOutOfRange, value), "key");
 
            return value;
        }

        private CharacterMetrics ConvertValue(object value) 
        {
            CharacterMetrics metrics = value as CharacterMetrics; 
            if (metrics != null) 
                return metrics;
 
            if (value != null)
                throw new ArgumentException(SR.Get(SRID.CannotConvertType, typeof(CharacterMetrics), value.GetType()));
            else
                throw new ArgumentNullException("value"); 
        }
 
        private struct Enumerator : SC.IDictionaryEnumerator, IEnumerator> 
        {
            private CharacterMetricsDictionary _dictionary; 
            private int _unicodeScalar;
            private CharacterMetrics _value;

            internal Enumerator(CharacterMetricsDictionary dictionary) 
            {
                _dictionary = dictionary; 
                _unicodeScalar = -1; 
                _value = null;
            } 

            void IDisposable.Dispose()
            {
            } 

            public bool MoveNext() 
            { 
                if (_unicodeScalar < int.MaxValue)
                { 
                    _value = _dictionary.GetNextValue(ref _unicodeScalar);
                }
                return _value != null;
            } 

            void SC.IEnumerator.Reset() 
            { 
                _unicodeScalar = -1;
            } 

            // Current object in the sequence, which for an IDictionaryEnumerator
            // is expected to be a DictionaryEntry.
            object SC.IEnumerator.Current 
            {
                get 
                { 
                    KeyValuePair entry = GetCurrentEntry();
                    return new SC.DictionaryEntry(entry.Key, entry.Value); 
                }
            }

            // Current property for generic enumerator. 
            public KeyValuePair Current
            { 
                get 
                {
                    return new KeyValuePair(_unicodeScalar, _value); 
                }
            }

            private KeyValuePair GetCurrentEntry() 
            {
                if (_value != null) 
                    return new KeyValuePair(_unicodeScalar, _value); 
                else
                    throw new InvalidOperationException(SR.Get(SRID.Enumerator_VerifyContext)); 
            }

            SC.DictionaryEntry SC.IDictionaryEnumerator.Entry
            { 
                get
                { 
                    KeyValuePair entry = GetCurrentEntry(); 
                    return new SC.DictionaryEntry(entry.Key, entry.Value);
                } 
            }

            object SC.IDictionaryEnumerator.Key
            { 
                get
                { 
                    return GetCurrentEntry().Key; 
                }
            } 

            object SC.IDictionaryEnumerator.Value
            {
                get 
                {
                    return GetCurrentEntry().Value; 
                } 
            }
        } 

        #endregion
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------ 
//
//  Microsoft Windows Client Platform
//  Copyright (C) Microsoft Corporation, 2002
// 
//  File:      CharacterMetricsDictionary.cs
// 
//  Contents:  CharacterMetricsDictionary 
//
//  Created:   6-6-05 Niklas Borson (niklasb) 
//
//-----------------------------------------------------------------------

using System; 
using SC=System.Collections;
using System.Collections.Generic; 
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 

// Allow suppression of presharp warnings
#pragma warning disable 1634, 1691
 
namespace System.Windows.Media
{ 
    ///  
    /// Dictionary of character metrics for a device font indexed by Unicode scalar value.
    ///  
    public sealed class CharacterMetricsDictionary : IDictionary, SC.IDictionary
    {
        /// 
        /// Constructs an empty CharacterMetricsDictionary object. 
        /// 
        internal CharacterMetricsDictionary() 
        { 
        }
 
        #region IEnumerable members

        /// 
        /// Returns an enumerator that iterates through the collection. 
        /// 
        [CLSCompliant(false)] 
        public IEnumerator> GetEnumerator() 
        {
            return new Enumerator(this); 
        }

        SC.IEnumerator SC.IEnumerable.GetEnumerator()
        { 
            return new Enumerator(this);
        } 
 
        SC.IDictionaryEnumerator SC.IDictionary.GetEnumerator()
        { 
            return new Enumerator(this);
        }

        ///  
        /// If the dictionary contains an entry for the specified character code, returns true
        /// and stores the CharacterMetrics in the value parameter; otherwise returns false and 
        /// sets value to null. 
        /// 
        public bool TryGetValue(int key, out CharacterMetrics value) 
        {
            value = GetValue(key);
            return value != null;
        } 

        #endregion 
 
        #region ICollection members
 
        /// 
        /// Gets the number of objects in the collection.
        /// 
        public int Count 
        {
            get 
            { 
                if (_count == 0)
                { 
                    _count = CountValues();
                }
                return _count;
            } 
        }
 
        ///  
        /// Gets a value indicating whether the collection is read-only.
        ///  
        public bool IsReadOnly
        {
            get { return false; }
        } 

        ///  
        /// Adds a character code and associated CharacterMetrics to the collection. 
        /// 
        [CLSCompliant(false)] 
        public void Add(KeyValuePair item)
        {
            SetValue(
                item.Key, 
                item.Value,
                true // failIfExists 
                ); 
        }
 
        /// 
        /// Removes all objects from the collection.
        /// 
        public void Clear() 
        {
            _count = 0; 
            _pageTable = null; 
        }
 
        /// 
        /// Determines whether the collection contains the specified characterCode-CharacterMetrics pair.
        /// 
        [CLSCompliant(false)] 
        public bool Contains(KeyValuePair item)
        { 
            // Suppress PRESharp warning that item.Value can be null; apparently PRESharp 
            // doesn't understand short circuit evaluation of operator &&.
#pragma warning suppress 56506 
            return item.Value != null && item.Value.Equals(GetValue(item.Key));
        }

        ///  
        /// Copies the contents of the collection to the specified array.
        ///  
        [CLSCompliant(false)] 
        public void CopyTo(KeyValuePair[] array, int index)
        { 
            if (array == null)
                throw new ArgumentNullException("array");

            if (index < 0) 
                throw new ArgumentOutOfRangeException("index");
 
            if (index >= array.Length) 
                throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_IndexGreaterThanOrEqualToArrayLength, "index", "array"));
 
            CharacterMetrics[][] pageTable = _pageTable;
            if (pageTable != null)
            {
                int k = index; 

                for (int i = 0; i < pageTable.Length; ++i) 
                { 
                    CharacterMetrics[] page = pageTable[i];
                    if (page != null) 
                    {
                        for (int j = 0; j < page.Length; ++j)
                        {
                            CharacterMetrics metrics = page[j]; 
                            if (metrics != null)
                            { 
                                if (k >= array.Length) 
                                    throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_NumberOfElementsExceedsArrayLength, index, "array"));
 
                                array[k++] = new KeyValuePair(
                                    (i << PageShift) | j,
                                    metrics
                                    ); 
                            }
                        } 
                    } 
                }
            } 
        }

        /// 
        /// Removes the specified characterCode-CharacterMetrics pair from the collection. 
        /// 
        [CLSCompliant(false)] 
        public bool Remove(KeyValuePair item) 
        {
            return item.Value != null && RemoveValue(item.Key, item.Value); 
        }

        bool SC.ICollection.IsSynchronized
        { 
            get { return false; }
        } 
 
        object SC.ICollection.SyncRoot
        { 
            get { return this; }
        }

        void SC.ICollection.CopyTo(Array array, int index) 
        {
            if (array == null) 
                throw new ArgumentNullException("array"); 

            if (index < 0) 
                throw new ArgumentOutOfRangeException("index");

            if (index >= array.Length)
                throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_IndexGreaterThanOrEqualToArrayLength, "index", "array")); 

            if (Count > array.Length - index) 
                throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_NumberOfElementsExceedsArrayLength, index, "array")); 

            SC.DictionaryEntry[] typedArray = array as SC.DictionaryEntry[]; 
            if (typedArray != null)
            {
                // it's an array of the exact type
                foreach (KeyValuePair item in this) 
                {
                    typedArray[index++] = new SC.DictionaryEntry(item.Key, item.Value); 
                } 
            }
            else 
            {
                // it's an array of some other type, e.g., object[]; make sure it's one dimensional
                if (array.Rank != 1)
                    throw new ArgumentException(SR.Get(SRID.Collection_CopyTo_ArrayCannotBeMultidimensional)); 

                // make sure the element type is compatible 
                Type elementType = array.GetType().GetElementType(); 
                if (!elementType.IsAssignableFrom(typeof(SC.DictionaryEntry)))
                    throw new ArgumentException(SR.Get(SRID.CannotConvertType, typeof(SC.DictionaryEntry), elementType)); 

                foreach (KeyValuePair item in this)
                {
                    array.SetValue(new SC.DictionaryEntry(item.Key, item.Value), index++); 
                }
            } 
        } 

        #endregion 

        #region IDictionary members

        ///  
        /// Adds a character code and associated CharacterMetrics to the collection.
        ///  
        public void Add(int key, CharacterMetrics value) 
        {
            SetValue(key, value, /* failIfExists = */ true); 
        }

        /// 
        /// Determines whether the collection contains the specified character code. 
        /// 
        public bool ContainsKey(int key) 
        { 
            return GetValue(key) != null;
        } 

        /// 
        /// Removes the specified character code and associated CharacterMetrics.
        ///  
        public bool Remove(int key)
        { 
            return RemoveValue(key, null); 
        }
 
        /// 
        /// Gets or sets the CharacterMetrics associated with the specified character code.
        /// 
        public CharacterMetrics this[int key] 
        {
            get { return GetValue(key); } 
            set { SetValue(key, value, /* failIfExists = */ false); } 
        }
 
        /// 
        /// Gets a collection containing the keys (character codes) in the dictionary.
        /// 
        [CLSCompliant(false)] 
        public ICollection Keys
        { 
            get { return GetKeys(); } 
        }
 
        /// 
        /// Gets a collection containing the values (strings) in the dictionary.
        /// 
        [CLSCompliant(false)] 
        public ICollection Values
        { 
            get { return GetValues(); } 
        }
 
        bool SC.IDictionary.IsFixedSize
        {
            get { return false; }
        } 

        object SC.IDictionary.this[object key] 
        { 
            get
            { 
                return (key is int) ? GetValue((int)key) : null;
            }

            set 
            {
                SetValue(ConvertKey(key), ConvertValue(value), /* failIfExists = */ false); 
            } 
        }
 
        SC.ICollection SC.IDictionary.Keys
        {
            get { return GetKeys(); }
        } 

        SC.ICollection SC.IDictionary.Values 
        { 
            get { return GetValues(); }
        } 

        void SC.IDictionary.Add(object key, object value)
        {
            SetValue(ConvertKey(key), ConvertValue(value), /* failIfExists = */ false); 
        }
 
        bool SC.IDictionary.Contains(object key) 
        {
            return key is int && GetValue((int)key) != null; 
        }

        void SC.IDictionary.Remove(object key)
        { 
            if (key is int)
            { 
                RemoveValue((int)key, null); 
            }
        } 
        #endregion

        #region Internal representation
 
        internal const int LastDeviceFontCharacterCode = 0xFFFF;
 
        internal const int PageShift = 8; 
        internal const int PageSize = 1 << PageShift;
        internal const int PageMask = PageSize - 1; 
        internal const int PageCount = (LastDeviceFontCharacterCode + 1 + (PageSize - 1)) / PageSize;

        private CharacterMetrics[][] _pageTable = null;
        private int _count = 0; 

        internal CharacterMetrics[] GetPage(int i) 
        { 
            return (_pageTable != null) ? _pageTable[i] : null;
        } 

        private CharacterMetrics[] GetPageFromUnicodeScalar(int unicodeScalar)
        {
            int i = unicodeScalar >> PageShift; 

            CharacterMetrics[] page; 
 
            if (_pageTable != null)
            { 
                page = _pageTable[i];
                if (page == null)
                {
                    _pageTable[i] = page = new CharacterMetrics[PageSize]; 
                }
            } 
            else 
            {
                _pageTable = new CharacterMetrics[PageCount][]; 
                _pageTable[i] = page = new CharacterMetrics[PageSize];
            }

            return page; 
        }
 
        private void SetValue(int key, CharacterMetrics value, bool failIfExists) 
        {
            if (key < 0 || key > LastDeviceFontCharacterCode) 
                throw new ArgumentOutOfRangeException(SR.Get(SRID.CodePointOutOfRange, key));

            if (value == null)
                throw new ArgumentNullException("value"); 

            CharacterMetrics[] page = GetPageFromUnicodeScalar(key); 
            int i = key & PageMask; 

            if (failIfExists && page[i] != null) 
                throw new ArgumentException(SR.Get(SRID.CollectionDuplicateKey, key));

            page[i] = value;
            _count = 0; 
        }
 
        internal CharacterMetrics GetValue(int key) 
        {
            CharacterMetrics metrics = null; 

            if (key >= 0 && key <= FontFamilyMap.LastUnicodeScalar && _pageTable != null)
            {
                CharacterMetrics[] page = _pageTable[key >> PageShift]; 
                if (page != null)
                    metrics = page[key & PageMask]; 
            } 

            return metrics; 
        }

        private bool RemoveValue(int key, CharacterMetrics value)
        { 
            if (key >= 0 && key <= FontFamilyMap.LastUnicodeScalar && _pageTable != null)
            { 
                CharacterMetrics[] page = _pageTable[key >> PageShift]; 
                if (page != null)
                { 
                    int i = key & PageMask;
                    CharacterMetrics metrics = page[i];

                    if (metrics != null && (value == null || metrics.Equals(value))) 
                    {
                        page[i] = null; 
                        _count = 0; 
                        return true;
                    } 
                }
            }
            return false;
        } 

        private CharacterMetrics GetNextValue(ref int unicodeScalar) 
        { 
            CharacterMetrics[][] pageTable = _pageTable;
            if (pageTable != null) 
            {
                int j = (unicodeScalar + 1) & PageMask;

                for (int i = (unicodeScalar + 1) >> PageShift; i < PageCount; ++i) 
                {
                    CharacterMetrics[] page = pageTable[i]; 
                    if (page != null) 
                    {
                        for (; j < PageSize; ++j) 
                        {
                            CharacterMetrics metrics = page[j];
                            if (metrics != null)
                            { 
                                unicodeScalar = (i << PageShift) | j;
                                return metrics; 
                            } 
                        }
 
                        j = 0;
                    }
                }
            } 

            unicodeScalar = int.MaxValue; 
            return null; 
        }
 
        private int CountValues()
        {
            int c = 0;
 
            CharacterMetrics[][] pageTable = _pageTable;
            if (pageTable != null) 
            { 
                for (int i = 0; i < pageTable.Length; ++i)
                { 
                    CharacterMetrics[] page = pageTable[i];
                    if (page != null)
                    {
                        for (int j = 0; j < page.Length; ++j) 
                        {
                            if (page[j] != null) 
                                ++c; 
                        }
                    } 
                }
            }

            return c; 
        }
 
        private int[] GetKeys() 
        {
            int[] result = new int[Count]; 
            int i = 0;
            foreach (KeyValuePair pair in this)
            {
                result[i++] = pair.Key; 
            }
            return result; 
        } 

        private CharacterMetrics[] GetValues() 
        {
            CharacterMetrics[] result = new CharacterMetrics[Count];
            int i = 0;
            foreach (KeyValuePair pair in this) 
            {
                result[i++] = pair.Value; 
            } 
            return result;
        } 

        internal static int ConvertKey(object key)
        {
            if (key == null) 
                throw new ArgumentNullException("key");
 
            int value; 

            string s = key as string; 
            if (s != null)
            {
                int i = 0;
                if (!FontFamilyMap.ParseHexNumber(s, ref i, out value) || i < s.Length) 
                    throw new ArgumentException(SR.Get(SRID.CannotConvertStringToType, s, "int"), "key");
            } 
            else if (key is int) 
            {
                value = (int)key; 
            }
            else
            {
                throw new ArgumentException(SR.Get(SRID.CannotConvertType, key.GetType(), "int"), "key"); 
            }
 
            if (value < 0 || value > FontFamilyMap.LastUnicodeScalar) 
                throw new ArgumentException(SR.Get(SRID.CodePointOutOfRange, value), "key");
 
            return value;
        }

        private CharacterMetrics ConvertValue(object value) 
        {
            CharacterMetrics metrics = value as CharacterMetrics; 
            if (metrics != null) 
                return metrics;
 
            if (value != null)
                throw new ArgumentException(SR.Get(SRID.CannotConvertType, typeof(CharacterMetrics), value.GetType()));
            else
                throw new ArgumentNullException("value"); 
        }
 
        private struct Enumerator : SC.IDictionaryEnumerator, IEnumerator> 
        {
            private CharacterMetricsDictionary _dictionary; 
            private int _unicodeScalar;
            private CharacterMetrics _value;

            internal Enumerator(CharacterMetricsDictionary dictionary) 
            {
                _dictionary = dictionary; 
                _unicodeScalar = -1; 
                _value = null;
            } 

            void IDisposable.Dispose()
            {
            } 

            public bool MoveNext() 
            { 
                if (_unicodeScalar < int.MaxValue)
                { 
                    _value = _dictionary.GetNextValue(ref _unicodeScalar);
                }
                return _value != null;
            } 

            void SC.IEnumerator.Reset() 
            { 
                _unicodeScalar = -1;
            } 

            // Current object in the sequence, which for an IDictionaryEnumerator
            // is expected to be a DictionaryEntry.
            object SC.IEnumerator.Current 
            {
                get 
                { 
                    KeyValuePair entry = GetCurrentEntry();
                    return new SC.DictionaryEntry(entry.Key, entry.Value); 
                }
            }

            // Current property for generic enumerator. 
            public KeyValuePair Current
            { 
                get 
                {
                    return new KeyValuePair(_unicodeScalar, _value); 
                }
            }

            private KeyValuePair GetCurrentEntry() 
            {
                if (_value != null) 
                    return new KeyValuePair(_unicodeScalar, _value); 
                else
                    throw new InvalidOperationException(SR.Get(SRID.Enumerator_VerifyContext)); 
            }

            SC.DictionaryEntry SC.IDictionaryEnumerator.Entry
            { 
                get
                { 
                    KeyValuePair entry = GetCurrentEntry(); 
                    return new SC.DictionaryEntry(entry.Key, entry.Value);
                } 
            }

            object SC.IDictionaryEnumerator.Key
            { 
                get
                { 
                    return GetCurrentEntry().Key; 
                }
            } 

            object SC.IDictionaryEnumerator.Value
            {
                get 
                {
                    return GetCurrentEntry().Value; 
                } 
            }
        } 

        #endregion
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

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