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
- DefaultBindingPropertyAttribute.cs
- WebCodeGenerator.cs
- Collection.cs
- InvariantComparer.cs
- TextEvent.cs
- EntityClientCacheEntry.cs
- DateBoldEvent.cs
- Region.cs
- RemoteWebConfigurationHostServer.cs
- SchemaObjectWriter.cs
- MarkerProperties.cs
- NTAccount.cs
- LinqMaximalSubtreeNominator.cs
- ScrollChrome.cs
- EntityDataSourceEntityTypeFilterItem.cs
- Int64KeyFrameCollection.cs
- RegistrySecurity.cs
- SecureStringHasher.cs
- IdentityValidationException.cs
- OdbcFactory.cs
- TextElement.cs
- ResourceExpressionEditorSheet.cs
- FastEncoderWindow.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- Convert.cs
- RoleGroup.cs
- XmlImplementation.cs
- TiffBitmapDecoder.cs
- Debug.cs
- EventSourceCreationData.cs
- CodeGroup.cs
- AlignmentYValidation.cs
- OpacityConverter.cs
- SqlFunctionAttribute.cs
- ViewGenResults.cs
- EdmItemCollection.cs
- XmlQueryOutput.cs
- ListViewHitTestInfo.cs
- ItemsPresenter.cs
- CodeIdentifier.cs
- WebPartDesigner.cs
- HttpHandlerAction.cs
- AppendHelper.cs
- GridEntryCollection.cs
- RenderContext.cs
- DateBoldEvent.cs
- PropertyPathWorker.cs
- WebPartExportVerb.cs
- GlyphRunDrawing.cs
- PersonalizationProviderCollection.cs
- DiagnosticsConfigurationHandler.cs
- Configuration.cs
- MappingMetadataHelper.cs
- ToolStripDropDownItemDesigner.cs
- MDIWindowDialog.cs
- PreloadedPackages.cs
- Misc.cs
- DataGridLinkButton.cs
- CodeCatchClauseCollection.cs
- HtmlControl.cs
- SqlTriggerAttribute.cs
- PackagePartCollection.cs
- AbsoluteQuery.cs
- SemanticBasicElement.cs
- CodeDelegateCreateExpression.cs
- ToolStripOverflowButton.cs
- CanonicalFontFamilyReference.cs
- IDQuery.cs
- ActiveXMessageFormatter.cs
- CompositeFontInfo.cs
- TemplateColumn.cs
- AccessibleObject.cs
- ScriptModule.cs
- ThemeDictionaryExtension.cs
- Win32MouseDevice.cs
- StrongNameKeyPair.cs
- HttpHeaderCollection.cs
- PropertyPathConverter.cs
- RecommendedAsConfigurableAttribute.cs
- ObjectDataSourceMethodEventArgs.cs
- Environment.cs
- SchemaImporterExtensionsSection.cs
- ComboBoxAutomationPeer.cs
- Menu.cs
- WebScriptEndpoint.cs
- ContainerParagraph.cs
- SourceElementsCollection.cs
- QuadraticBezierSegment.cs
- WebBrowserNavigatingEventHandler.cs
- VisualTreeUtils.cs
- ChameleonKey.cs
- PaintValueEventArgs.cs
- MetafileHeader.cs
- StylusLogic.cs
- WSHttpBindingBase.cs
- ScriptResourceMapping.cs
- ImageAutomationPeer.cs
- RC2CryptoServiceProvider.cs
- InputProcessorProfiles.cs
- DescendantQuery.cs