Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / MS / Internal / FontFace / CompositeFontInfo.cs / 1 / CompositeFontInfo.cs
//+------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2003 // // File: CompositeFontInfo.cs // // Contents: Composite font info parsed from composite font file // // Created: 7-30-2003 Worachai Chaoweeraprasit (wchao) // //----------------------------------------------------------------------- using System; using System.Globalization; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Markup; using System.Windows.Media; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace MS.Internal.FontFace { ////// Composite font info /// internal sealed class CompositeFontInfo { private LanguageSpecificStringDictionary _familyNames; private double _baseline; private double _lineSpacing; private FamilyTypefaceCollection _familyTypefaces; private FontFamilyMapCollection _familyMaps; private ushort[] _defaultFamilyMapRanges; private Dictionary_familyMapRangesByLanguage; private const int InitialCultureCount = 1; // at least a familyMap for one locale available private const int InitialTargetFamilyCount = 1; /// /// Construct a composite font /// internal CompositeFontInfo() { _familyNames = new LanguageSpecificStringDictionary(new Dictionary(InitialCultureCount)); _familyMaps = new FontFamilyMapCollection(this); _defaultFamilyMapRanges = EmptyFamilyMapRanges; } /// /// Called by FontFamilyMapCollection when a FontFamilyMap is being added. /// internal void PrepareToAddFamilyMap(FontFamilyMap familyMap) { // Validate parameters. if (familyMap == null) throw new ArgumentNullException("familyMap"); if (string.IsNullOrEmpty(familyMap.Target)) throw new ArgumentException(SR.Get(SRID.FamilyMap_TargetNotSet)); // If it's culture-specific make sure it's in the hash table. if (familyMap.Language != null) { if (_familyMapRangesByLanguage == null) { _familyMapRangesByLanguage = new Dictionary(InitialCultureCount); _familyMapRangesByLanguage.Add(familyMap.Language, EmptyFamilyMapRanges); } else if (!_familyMapRangesByLanguage.ContainsKey(familyMap.Language)) { _familyMapRangesByLanguage.Add(familyMap.Language, EmptyFamilyMapRanges); } } } #region family map ranges (skip lists) /// /// FontFamilyMap ranges (aka. skip lists) are an optimization to speed up family map lookup. /// /// OBSERVABLE BEHAVIOR /// /// The observable behavior of family map lookup should be as if we traverse the /// list of family maps sequentially and return the first one that matches both /// the text culture and the code point. /// /// The language matches if the family map language is null, or is equal to the text /// language, or if the family map language's "range" includes the text culture. /// This logic is implemented by FontFamilyMap.MatchCulture() and /// FontFamilyMap.MatchLanguage, which call XmlLanguage.RangeIncludes(). /// /// /// SKIP LISTS /// /// Skip lists allow us to avoid doing the culture comparisons described above on /// every character lookup. Instead, we generate a skip list once the first time we /// use a particular culture, and then use the skip list to determine which family /// maps to look at and which to skip. /// /// A skip list is an array of ushort. The first array member represents the size of /// the family map list and is used to determine whether the skip list is invalid /// (see Invalidating Skip Lists). The remainder of the skip list (beginning at /// at index FirstFamilyMapRange) consists of pairs of ushort values. Each pair /// denotes a range of family maps in the family maps list; the first member of the /// pair is the index of the first element in the range, and the second is the index /// one past the last element in the range. Collectively, these ranges include all of /// the family maps that should be included in the lookup for a culture, i.e., the /// culture associated with the skip list. /// /// Following is an example of a family map list and the corresponding skip lists: /// /// 0 1 2 3 4 5 6 7 8 /// +-------+-------+-------+-------+-------+-------+-------+-------+ /// | ja | ja | ko | ko | zh-CHT| zh-CHS| any | any | /// +-------+-------+-------+-------+-------+-------+-------+-------+ /// /// "ja" -> (0,2) (6,8) /// "ko" -> (2,4) (6,8) /// "zh-CHT" -> (4,5) (6,8) /// "zh-CHS" -> (5,8) /// default -> (6,8) /// /// INVALIDATING SKIP LISTS /// /// A skip list becomes invalid whenever the family map list changes. To avoid /// recreating skip lists every time a family map is added, skip lists are created /// lazily. Skip lists are added to the _familyMapRangesByLanguage hash table as /// family maps are added, but each skip list is initialized by EmptyFamilyMapRanges. /// /// After a skip list has been created, a may be rendered invalid by subsequent /// changes to the family map list. We have two mechanisms to detect this. /// /// (1) Each skip list includes (as its first member) the size of the family /// map when the skip list was created. Additions to or insertions into /// the list can therefore be detected because the sizes no longer match. /// /// (2) For all other changes (removing items changing items), the FamilyMaps /// list calls InvalidateFamilyMapRanges(), which setes all skip lists to /// EmptyFamilyMapRanges. /// /// private static readonly ushort[] EmptyFamilyMapRanges = new ushort[] { 0 }; private const int InitialFamilyMapRangesCapacity = 7; // count + 3 ranges internal const int FirstFamilyMapRange = 1; ////// Called by FontFamilyMapCollection when a change occurs that renders all /// family map ranges potentially invalid. /// internal void InvalidateFamilyMapRanges() { _defaultFamilyMapRanges = EmptyFamilyMapRanges; if (_familyMapRangesByLanguage != null) { Dictionarytable = new Dictionary (_familyMapRangesByLanguage.Count); foreach (XmlLanguage language in _familyMapRangesByLanguage.Keys) { table.Add(language, EmptyFamilyMapRanges); } _familyMapRangesByLanguage = table; } } /// /// Returns information about which family maps apply to the specified culture. /// The return value is used by GetFamilyMapOfChar. /// internal ushort[] GetFamilyMapsOfLanguage(XmlLanguage language) { ushort[] ranges = null; // Look for a family map range for the specified language or one of its matching languages if (_familyMapRangesByLanguage != null && language != null) { foreach (XmlLanguage matchingLanguage in language.MatchingLanguages) { // break out of loop to handle default list of ranges if (matchingLanguage.IetfLanguageTag.Length == 0) break; if (_familyMapRangesByLanguage.TryGetValue(matchingLanguage, out ranges)) { // Recreate the list of ranges if we've added more family maps. if (!IsFamilyMapRangesValid(ranges)) { ranges = CreateFamilyMapRanges(matchingLanguage); _familyMapRangesByLanguage[matchingLanguage] = ranges; } return ranges; } } } // Use the default list of ranges (containing only family maps that match // any culture); recreate it if we've added more family maps. if (!IsFamilyMapRangesValid(_defaultFamilyMapRanges)) { _defaultFamilyMapRanges = CreateFamilyMapRanges(null); } return _defaultFamilyMapRanges; } ////// Gets the first FontFamilyMap that matches the specified Unicode scalar value. /// /// Return value of GetFamilyMapsOfCulture. /// Character to map. ///FontFamilyMap or null. internal FontFamilyMap GetFamilyMapOfChar(ushort[] familyMapRanges, int ch) { Debug.Assert(IsFamilyMapRangesValid(familyMapRanges)); // Iterate over the ushort pairs in the skip list. for (int i = FirstFamilyMapRange; i < familyMapRanges.Length; i += 2) { // Each pair specifies a range in the family map list. int begin = familyMapRanges[i]; int end = familyMapRanges[i + 1]; Debug.Assert(begin < end && end <= _familyMaps.Count); // Iterate over the family maps in the specified range. for (int j = begin; j < end; ++j) { FontFamilyMap familyMap = _familyMaps[j]; Invariant.Assert(familyMap != null); if (familyMap.InRange(ch)) return familyMap; } } return FontFamilyMap.Default; } private bool IsFamilyMapRangesValid(ushort[] familyMapRanges) { return familyMapRanges[0] == _familyMaps.Count; } private ushort[] CreateFamilyMapRanges(XmlLanguage language) { // We could use an ArrayList, but a ushort[] is not much more code // and requires many fewer boxed objects. ushort[] ranges = new ushort[InitialFamilyMapRangesCapacity]; ranges[0] = (ushort)_familyMaps.Count; int count = 1; Debug.Assert(count == FirstFamilyMapRange); for (int i = 0; i < _familyMaps.Count; ++i) { if (FontFamilyMap.MatchLanguage(_familyMaps[i].Language, language)) { // grow ranges if necessary. if (count + 2 > ranges.Length) { ushort[] temp = new ushort[ranges.Length * 2 - FirstFamilyMapRange]; ranges.CopyTo(temp, 0); ranges = temp; } // beginning of range ranges[count++] = (ushort)i; ++i; while (i < _familyMaps.Count && FontFamilyMap.MatchLanguage(_familyMaps[i].Language, language)) { ++i; } // end of range, i.e., last index + 1 ranges[count++] = (ushort)i; } } // reallocate ranges to the exact size required if (count < ranges.Length) { ushort[] temp = new ushort[count]; Array.Copy(ranges, temp, count); ranges = temp; } return ranges; } #endregion ////// List of typefaces; can be null. /// internal FamilyTypefaceCollection FamilyTypefaces { get { return _familyTypefaces; } } ////// Gets the list of family typefaces, creating it if necessary. /// internal FamilyTypefaceCollection GetFamilyTypefaceList() { if (_familyTypefaces == null) _familyTypefaces = new FamilyTypefaceCollection(); return _familyTypefaces; } ////// Distance from character cell top to English baseline relative to em size. /// internal double Baseline { get { return _baseline; } set { CompositeFontParser.VerifyNonNegativeMultiplierOfEm("Baseline", ref value); _baseline = value; } } ////// Additional line spacing after Height relative to em size /// internal double LineSpacing { get { return _lineSpacing; } set { CompositeFontParser.VerifyPositiveMultiplierOfEm("LineSpacing", ref value); _lineSpacing = value; } } ////// Dictionary of names by culture. /// internal LanguageSpecificStringDictionary FamilyNames { get { return _familyNames; } } ////// List of family maps. /// internal FontFamilyMapCollection FamilyMaps { get { return _familyMaps; } } ////// Collection of cultures associated with family maps; can be null /// if all family maps are culture-independent. /// internal ICollectionFamilyMapLanguages { get { if (_familyMapRangesByLanguage != null) return _familyMapRangesByLanguage.Keys; else return null; } } } } // 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, 2003 // // File: CompositeFontInfo.cs // // Contents: Composite font info parsed from composite font file // // Created: 7-30-2003 Worachai Chaoweeraprasit (wchao) // //----------------------------------------------------------------------- using System; using System.Globalization; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Markup; using System.Windows.Media; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace MS.Internal.FontFace { /// /// Composite font info /// internal sealed class CompositeFontInfo { private LanguageSpecificStringDictionary _familyNames; private double _baseline; private double _lineSpacing; private FamilyTypefaceCollection _familyTypefaces; private FontFamilyMapCollection _familyMaps; private ushort[] _defaultFamilyMapRanges; private Dictionary_familyMapRangesByLanguage; private const int InitialCultureCount = 1; // at least a familyMap for one locale available private const int InitialTargetFamilyCount = 1; /// /// Construct a composite font /// internal CompositeFontInfo() { _familyNames = new LanguageSpecificStringDictionary(new Dictionary(InitialCultureCount)); _familyMaps = new FontFamilyMapCollection(this); _defaultFamilyMapRanges = EmptyFamilyMapRanges; } /// /// Called by FontFamilyMapCollection when a FontFamilyMap is being added. /// internal void PrepareToAddFamilyMap(FontFamilyMap familyMap) { // Validate parameters. if (familyMap == null) throw new ArgumentNullException("familyMap"); if (string.IsNullOrEmpty(familyMap.Target)) throw new ArgumentException(SR.Get(SRID.FamilyMap_TargetNotSet)); // If it's culture-specific make sure it's in the hash table. if (familyMap.Language != null) { if (_familyMapRangesByLanguage == null) { _familyMapRangesByLanguage = new Dictionary(InitialCultureCount); _familyMapRangesByLanguage.Add(familyMap.Language, EmptyFamilyMapRanges); } else if (!_familyMapRangesByLanguage.ContainsKey(familyMap.Language)) { _familyMapRangesByLanguage.Add(familyMap.Language, EmptyFamilyMapRanges); } } } #region family map ranges (skip lists) /// /// FontFamilyMap ranges (aka. skip lists) are an optimization to speed up family map lookup. /// /// OBSERVABLE BEHAVIOR /// /// The observable behavior of family map lookup should be as if we traverse the /// list of family maps sequentially and return the first one that matches both /// the text culture and the code point. /// /// The language matches if the family map language is null, or is equal to the text /// language, or if the family map language's "range" includes the text culture. /// This logic is implemented by FontFamilyMap.MatchCulture() and /// FontFamilyMap.MatchLanguage, which call XmlLanguage.RangeIncludes(). /// /// /// SKIP LISTS /// /// Skip lists allow us to avoid doing the culture comparisons described above on /// every character lookup. Instead, we generate a skip list once the first time we /// use a particular culture, and then use the skip list to determine which family /// maps to look at and which to skip. /// /// A skip list is an array of ushort. The first array member represents the size of /// the family map list and is used to determine whether the skip list is invalid /// (see Invalidating Skip Lists). The remainder of the skip list (beginning at /// at index FirstFamilyMapRange) consists of pairs of ushort values. Each pair /// denotes a range of family maps in the family maps list; the first member of the /// pair is the index of the first element in the range, and the second is the index /// one past the last element in the range. Collectively, these ranges include all of /// the family maps that should be included in the lookup for a culture, i.e., the /// culture associated with the skip list. /// /// Following is an example of a family map list and the corresponding skip lists: /// /// 0 1 2 3 4 5 6 7 8 /// +-------+-------+-------+-------+-------+-------+-------+-------+ /// | ja | ja | ko | ko | zh-CHT| zh-CHS| any | any | /// +-------+-------+-------+-------+-------+-------+-------+-------+ /// /// "ja" -> (0,2) (6,8) /// "ko" -> (2,4) (6,8) /// "zh-CHT" -> (4,5) (6,8) /// "zh-CHS" -> (5,8) /// default -> (6,8) /// /// INVALIDATING SKIP LISTS /// /// A skip list becomes invalid whenever the family map list changes. To avoid /// recreating skip lists every time a family map is added, skip lists are created /// lazily. Skip lists are added to the _familyMapRangesByLanguage hash table as /// family maps are added, but each skip list is initialized by EmptyFamilyMapRanges. /// /// After a skip list has been created, a may be rendered invalid by subsequent /// changes to the family map list. We have two mechanisms to detect this. /// /// (1) Each skip list includes (as its first member) the size of the family /// map when the skip list was created. Additions to or insertions into /// the list can therefore be detected because the sizes no longer match. /// /// (2) For all other changes (removing items changing items), the FamilyMaps /// list calls InvalidateFamilyMapRanges(), which setes all skip lists to /// EmptyFamilyMapRanges. /// /// private static readonly ushort[] EmptyFamilyMapRanges = new ushort[] { 0 }; private const int InitialFamilyMapRangesCapacity = 7; // count + 3 ranges internal const int FirstFamilyMapRange = 1; ////// Called by FontFamilyMapCollection when a change occurs that renders all /// family map ranges potentially invalid. /// internal void InvalidateFamilyMapRanges() { _defaultFamilyMapRanges = EmptyFamilyMapRanges; if (_familyMapRangesByLanguage != null) { Dictionarytable = new Dictionary (_familyMapRangesByLanguage.Count); foreach (XmlLanguage language in _familyMapRangesByLanguage.Keys) { table.Add(language, EmptyFamilyMapRanges); } _familyMapRangesByLanguage = table; } } /// /// Returns information about which family maps apply to the specified culture. /// The return value is used by GetFamilyMapOfChar. /// internal ushort[] GetFamilyMapsOfLanguage(XmlLanguage language) { ushort[] ranges = null; // Look for a family map range for the specified language or one of its matching languages if (_familyMapRangesByLanguage != null && language != null) { foreach (XmlLanguage matchingLanguage in language.MatchingLanguages) { // break out of loop to handle default list of ranges if (matchingLanguage.IetfLanguageTag.Length == 0) break; if (_familyMapRangesByLanguage.TryGetValue(matchingLanguage, out ranges)) { // Recreate the list of ranges if we've added more family maps. if (!IsFamilyMapRangesValid(ranges)) { ranges = CreateFamilyMapRanges(matchingLanguage); _familyMapRangesByLanguage[matchingLanguage] = ranges; } return ranges; } } } // Use the default list of ranges (containing only family maps that match // any culture); recreate it if we've added more family maps. if (!IsFamilyMapRangesValid(_defaultFamilyMapRanges)) { _defaultFamilyMapRanges = CreateFamilyMapRanges(null); } return _defaultFamilyMapRanges; } ////// Gets the first FontFamilyMap that matches the specified Unicode scalar value. /// /// Return value of GetFamilyMapsOfCulture. /// Character to map. ///FontFamilyMap or null. internal FontFamilyMap GetFamilyMapOfChar(ushort[] familyMapRanges, int ch) { Debug.Assert(IsFamilyMapRangesValid(familyMapRanges)); // Iterate over the ushort pairs in the skip list. for (int i = FirstFamilyMapRange; i < familyMapRanges.Length; i += 2) { // Each pair specifies a range in the family map list. int begin = familyMapRanges[i]; int end = familyMapRanges[i + 1]; Debug.Assert(begin < end && end <= _familyMaps.Count); // Iterate over the family maps in the specified range. for (int j = begin; j < end; ++j) { FontFamilyMap familyMap = _familyMaps[j]; Invariant.Assert(familyMap != null); if (familyMap.InRange(ch)) return familyMap; } } return FontFamilyMap.Default; } private bool IsFamilyMapRangesValid(ushort[] familyMapRanges) { return familyMapRanges[0] == _familyMaps.Count; } private ushort[] CreateFamilyMapRanges(XmlLanguage language) { // We could use an ArrayList, but a ushort[] is not much more code // and requires many fewer boxed objects. ushort[] ranges = new ushort[InitialFamilyMapRangesCapacity]; ranges[0] = (ushort)_familyMaps.Count; int count = 1; Debug.Assert(count == FirstFamilyMapRange); for (int i = 0; i < _familyMaps.Count; ++i) { if (FontFamilyMap.MatchLanguage(_familyMaps[i].Language, language)) { // grow ranges if necessary. if (count + 2 > ranges.Length) { ushort[] temp = new ushort[ranges.Length * 2 - FirstFamilyMapRange]; ranges.CopyTo(temp, 0); ranges = temp; } // beginning of range ranges[count++] = (ushort)i; ++i; while (i < _familyMaps.Count && FontFamilyMap.MatchLanguage(_familyMaps[i].Language, language)) { ++i; } // end of range, i.e., last index + 1 ranges[count++] = (ushort)i; } } // reallocate ranges to the exact size required if (count < ranges.Length) { ushort[] temp = new ushort[count]; Array.Copy(ranges, temp, count); ranges = temp; } return ranges; } #endregion ////// List of typefaces; can be null. /// internal FamilyTypefaceCollection FamilyTypefaces { get { return _familyTypefaces; } } ////// Gets the list of family typefaces, creating it if necessary. /// internal FamilyTypefaceCollection GetFamilyTypefaceList() { if (_familyTypefaces == null) _familyTypefaces = new FamilyTypefaceCollection(); return _familyTypefaces; } ////// Distance from character cell top to English baseline relative to em size. /// internal double Baseline { get { return _baseline; } set { CompositeFontParser.VerifyNonNegativeMultiplierOfEm("Baseline", ref value); _baseline = value; } } ////// Additional line spacing after Height relative to em size /// internal double LineSpacing { get { return _lineSpacing; } set { CompositeFontParser.VerifyPositiveMultiplierOfEm("LineSpacing", ref value); _lineSpacing = value; } } ////// Dictionary of names by culture. /// internal LanguageSpecificStringDictionary FamilyNames { get { return _familyNames; } } ////// List of family maps. /// internal FontFamilyMapCollection FamilyMaps { get { return _familyMaps; } } ////// Collection of cultures associated with family maps; can be null /// if all family maps are culture-independent. /// internal ICollectionFamilyMapLanguages { get { if (_familyMapRangesByLanguage != null) return _familyMapRangesByLanguage.Keys; else return null; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- KeyValuePair.cs
- CollectionViewSource.cs
- DefaultMemberAttribute.cs
- QuaternionAnimationUsingKeyFrames.cs
- IgnoreSection.cs
- DataTablePropertyDescriptor.cs
- MatchingStyle.cs
- ListDesigner.cs
- DBSchemaRow.cs
- ActiveXHost.cs
- RemoteWebConfigurationHostStream.cs
- BaseTypeViewSchema.cs
- ToolStripItemDesigner.cs
- ExpressionConverter.cs
- MarshalByValueComponent.cs
- DataGridViewTopRowAccessibleObject.cs
- Panel.cs
- LambdaSerializationException.cs
- Image.cs
- TrackingMemoryStreamFactory.cs
- DataGridViewLinkColumn.cs
- RequiredFieldValidator.cs
- TimeSpanStorage.cs
- DetailsViewInsertEventArgs.cs
- Table.cs
- UIHelper.cs
- ECDiffieHellmanCng.cs
- InheritanceAttribute.cs
- DataSourceView.cs
- ExtenderProvidedPropertyAttribute.cs
- LoginAutoFormat.cs
- SqlCacheDependencyDatabaseCollection.cs
- OleDbCommand.cs
- ThreadPoolTaskScheduler.cs
- SingleAnimationUsingKeyFrames.cs
- OracleRowUpdatingEventArgs.cs
- RoleGroupCollection.cs
- FactoryGenerator.cs
- HttpServerVarsCollection.cs
- PropertyChangingEventArgs.cs
- OdbcEnvironmentHandle.cs
- InputEventArgs.cs
- ColorComboBox.cs
- SafeArrayTypeMismatchException.cs
- StyleXamlParser.cs
- HttpCapabilitiesBase.cs
- EtwTrace.cs
- dataobject.cs
- AdornerLayer.cs
- Transactions.cs
- SQLBinaryStorage.cs
- BufferedGraphics.cs
- ArraySegment.cs
- ColorKeyFrameCollection.cs
- ChtmlTextWriter.cs
- SymbolType.cs
- WebRequestModulesSection.cs
- WebServiceMethodData.cs
- LogicalExpr.cs
- SByte.cs
- ExclusiveCanonicalizationTransform.cs
- BaseComponentEditor.cs
- basemetadatamappingvisitor.cs
- Random.cs
- SQLUtility.cs
- SettingsSavedEventArgs.cs
- basenumberconverter.cs
- KeyEvent.cs
- FontNamesConverter.cs
- MaterialCollection.cs
- OrderByExpression.cs
- SqlUdtInfo.cs
- RequiredAttributeAttribute.cs
- SourceElementsCollection.cs
- TabPage.cs
- CursorInteropHelper.cs
- DBConnectionString.cs
- SafeCoTaskMem.cs
- CompilerErrorCollection.cs
- WorkflowMessageEventHandler.cs
- Relationship.cs
- ForceCopyBuildProvider.cs
- TypeConstant.cs
- WorkflowInstanceExtensionProvider.cs
- WindowsTokenRoleProvider.cs
- OleDbReferenceCollection.cs
- SqlWorkflowInstanceStore.cs
- NullReferenceException.cs
- Transform.cs
- XmlUrlEditor.cs
- WebPartExportVerb.cs
- XsltSettings.cs
- DesignerLoader.cs
- ControlEvent.cs
- CodeDOMProvider.cs
- ObjectStateManager.cs
- BuilderElements.cs
- DiffuseMaterial.cs
- QilFunction.cs
- ConfigurationStrings.cs