Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / 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 [....] ([....])
//
//-----------------------------------------------------------------------
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)
{
Dictionary table = 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 ICollection FamilyMapLanguages
{
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
- DispatchChannelSink.cs
- HtmlInputImage.cs
- MemberNameValidator.cs
- SqlClientPermission.cs
- WindowsTreeView.cs
- AddingNewEventArgs.cs
- Visual.cs
- DataTableReader.cs
- EntityDataSourceWizardForm.cs
- ServiceDeploymentInfo.cs
- WindowsNonControl.cs
- PrefixQName.cs
- XmlDataSource.cs
- AuthenticationModuleElementCollection.cs
- ListBindingHelper.cs
- wpf-etw.cs
- Condition.cs
- Sql8ExpressionRewriter.cs
- ParseNumbers.cs
- SlipBehavior.cs
- CodeAccessSecurityEngine.cs
- GreenMethods.cs
- ManifestResourceInfo.cs
- Attributes.cs
- WebPartConnectionsCloseVerb.cs
- SelectionUIService.cs
- LinearKeyFrames.cs
- WebPartTracker.cs
- ServiceKnownTypeAttribute.cs
- UrlPath.cs
- RowToParametersTransformer.cs
- PathSegmentCollection.cs
- PropertyStore.cs
- OletxResourceManager.cs
- HostExecutionContextManager.cs
- PseudoWebRequest.cs
- Size3DValueSerializer.cs
- EventDescriptor.cs
- AdapterUtil.cs
- XamlTypeMapperSchemaContext.cs
- FileDialogCustomPlacesCollection.cs
- CacheChildrenQuery.cs
- Material.cs
- MessageBox.cs
- BaseDataList.cs
- LazyLoadBehavior.cs
- ConditionChanges.cs
- ExtensionSimplifierMarkupObject.cs
- XNodeNavigator.cs
- FixedSOMElement.cs
- base64Transforms.cs
- StrokeNode.cs
- ObjectDataSourceMethodEventArgs.cs
- SymmetricAlgorithm.cs
- CompletedAsyncResult.cs
- DashStyle.cs
- TraceUtils.cs
- DataSvcMapFileSerializer.cs
- Zone.cs
- StringUtil.cs
- WsdlExporter.cs
- SignerInfo.cs
- FieldAccessException.cs
- MD5CryptoServiceProvider.cs
- XmlParserContext.cs
- WorkflowInstanceQuery.cs
- XhtmlConformanceSection.cs
- StreamHelper.cs
- SourceChangedEventArgs.cs
- SchemaCreator.cs
- StylusPointPropertyInfo.cs
- MetadataPropertyvalue.cs
- WebPageTraceListener.cs
- RoleManagerSection.cs
- SymDocumentType.cs
- DbMetaDataCollectionNames.cs
- Tool.cs
- XmlChildEnumerator.cs
- ThreadExceptionEvent.cs
- OdbcRowUpdatingEvent.cs
- IisTraceWebEventProvider.cs
- TraceXPathNavigator.cs
- QueryCursorEventArgs.cs
- RayMeshGeometry3DHitTestResult.cs
- ErrorWrapper.cs
- TypeUsage.cs
- FontStretch.cs
- InkCanvasFeedbackAdorner.cs
- SmiEventStream.cs
- GenerateTemporaryAssemblyTask.cs
- RefreshPropertiesAttribute.cs
- StringCollection.cs
- RoutedEventHandlerInfo.cs
- ObjectStateFormatter.cs
- FactoryMaker.cs
- DiscriminatorMap.cs
- DefaultPrintController.cs
- LayoutSettings.cs
- XamlContextStack.cs
- Composition.cs