Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / TextFormatting / TextShapeableCharacters.cs / 1599983 / TextShapeableCharacters.cs
//------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation // // File: TextShapeableCharacters.cs // // Contents: Implementation of text shapeable symbols for characters // // Spec: http://team/sites/Avalon/Specs/Text%20Formatting%20API.doc // // Created: 1-2-2004 Worachai Chaoweeraprasit (wchao) // History: 1-19-2004 garyyyang: Change the class to internal // //----------------------------------------------------------------------- using System; using System.Diagnostics; using System.Globalization; using System.Collections; using System.Collections.Generic; using System.Security; using System.Windows; using System.Windows.Markup; // for XmlLanguage using System.Windows.Media; using MS.Internal; using MS.Internal.FontCache; using MS.Internal.TextFormatting; using MS.Internal.Shaping; using MS.Internal.Text.TextInterface; namespace System.Windows.Media.TextFormatting { ////// A specialized TextShapeableSymbols implemented by TextFormatter to represent /// a collection of glyphs from a physical typeface. /// internal sealed class TextShapeableCharacters : TextShapeableSymbols { private CharacterBufferRange _characterBufferRange; private TextFormattingMode _textFormattingMode; private bool _isSideways; private TextRunProperties _properties; private double _emSize; // after-scaled private ItemProps _textItem; private ShapeTypeface _shapeTypeface; private bool _nullShape; #region Constructors ////// Construct a shapeable characters object /// ////// The shapeTypeface parameter can be null if and only if CheckFastPathNominalGlyphs /// has previously returned true. /// internal TextShapeableCharacters( CharacterBufferRange characterRange, TextRunProperties properties, double emSize, ItemProps textItem, ShapeTypeface shapeTypeface, bool nullShape, TextFormattingMode textFormattingMode, bool isSideways ) { _isSideways = isSideways; _textFormattingMode = textFormattingMode; _characterBufferRange = characterRange; _properties = properties; _emSize = emSize; _textItem = textItem; _shapeTypeface = shapeTypeface; _nullShape = nullShape; } #endregion #region TextRun implementation ////// Character reference /// public sealed override CharacterBufferReference CharacterBufferReference { get { return _characterBufferRange.CharacterBufferReference; } } ////// Character length of the run /// public sealed override int Length { get { return _characterBufferRange.Length; } } ////// A set of properties shared by every characters in the run /// public sealed override TextRunProperties Properties { get { return _properties; } } #endregion #region TextShapeableSymbols implementation ////// Compute a shaped glyph run object from specified glyph-based info /// internal sealed override GlyphRun ComputeShapedGlyphRun( Point origin, char[] characterString, ushort[] clusterMap, ushort[] glyphIndices, IListglyphAdvances, IList glyphOffsets, bool rightToLeft, bool sideways ) { Invariant.Assert(_shapeTypeface != null); Invariant.Assert(glyphIndices != null); // Device fonts are only used through the LS non-glyphed code path. Only when a DigitCulture is set // will a potential device font be ignored and come through shaping. Invariant.Assert(_shapeTypeface.DeviceFont == null || _textItem.DigitCulture != null); bool[] caretStops = null; if ( clusterMap != null && (HasExtendedCharacter || NeedsCaretInfo) ) { caretStops = new bool[clusterMap.Length + 1]; // caret stops at cluster boundaries, the first and the last entries are always set caretStops[0] = true; caretStops[clusterMap.Length] = true; ushort lastGlyph = clusterMap[0]; for (int i = 1; i < clusterMap.Length; i++) { ushort glyph = clusterMap[i]; if (glyph != lastGlyph) { caretStops[i] = true; lastGlyph = glyph; } } } return GlyphRun.TryCreate( _shapeTypeface.GlyphTypeface, (rightToLeft ? 1 : 0), sideways, _emSize, glyphIndices, origin, glyphAdvances, glyphOffsets, characterString, null, clusterMap, caretStops, XmlLanguage.GetLanguage(CultureMapper.GetSpecificCulture(_properties.CultureInfo).IetfLanguageTag), _textFormattingMode ); } private GlyphTypeface GetGlyphTypeface(out bool nullFont) { GlyphTypeface glyphTypeface; if (_shapeTypeface == null) { // We're in the optimized path where the GlyphTypeface depends only // on the Typeface, not on the particular input characters. Typeface typeface = _properties.Typeface; // Get the GlyphTypeface. glyphTypeface = typeface.TryGetGlyphTypeface(); // If Typeface does not specify *any* valid font family, then we use // the GlyphTypeface for Arial but only to display missing glyphs. nullFont = typeface.NullFont; } else { // Font linking has mapped the input to a specific GlyphTypeface. glyphTypeface = _shapeTypeface.GlyphTypeface; // If font linking could not find *any* physical font family, then we // use the GlyphTypeface for Arial but only to display missing glyphs. nullFont = _nullShape; } Invariant.Assert(glyphTypeface != null); return glyphTypeface; } /// /// Compute unshaped glyph run object from the specified character-based info /// internal sealed override GlyphRun ComputeUnshapedGlyphRun( Point origin, char[] characterString, IListcharacterAdvances ) { bool nullFont; GlyphTypeface glyphTypeface = GetGlyphTypeface(out nullFont); Invariant.Assert(glyphTypeface != null); return glyphTypeface.ComputeUnshapedGlyphRun( origin, new CharacterBufferRange( characterString, 0, // offsetToFirstChar characterString.Length ), characterAdvances, _emSize, _properties.FontHintingEmSize, nullFont, CultureMapper.GetSpecificCulture(_properties.CultureInfo), (_shapeTypeface == null || _shapeTypeface.DeviceFont == null) ? null : _shapeTypeface.DeviceFont.Name, _textFormattingMode ); } /// /// Draw glyph run to the drawing surface /// internal sealed override void Draw( DrawingContext drawingContext, Brush foregroundBrush, GlyphRun glyphRun ) { if (drawingContext == null) throw new ArgumentNullException("drawingContext"); glyphRun.EmitBackground(drawingContext, _properties.BackgroundBrush); drawingContext.DrawGlyphRun( foregroundBrush != null ? foregroundBrush : _properties.ForegroundBrush, glyphRun ); } internal override double EmSize { get { return _emSize; } } internal override MS.Internal.Text.TextInterface.ItemProps ItemProps { get { return _textItem; } } ////// Get advance widths of unshaped characters /// ////// Critical: This code deals with pointers and calls SC methods like GetAdvanceWidthsUnshaped /// [SecurityCritical] internal sealed override unsafe void GetAdvanceWidthsUnshaped( char* characterString, int characterLength, double scalingFactor, int* advanceWidthsUnshaped ) { if (!IsShapingRequired) { if ( (_shapeTypeface != null) && (_shapeTypeface.DeviceFont != null)) { // Use device font to compute advance widths _shapeTypeface.DeviceFont.GetAdvanceWidths( characterString, characterLength, _emSize * scalingFactor, advanceWidthsUnshaped ); } else { bool nullFont; GlyphTypeface glyphTypeface = GetGlyphTypeface(out nullFont); Invariant.Assert(glyphTypeface != null); glyphTypeface.GetAdvanceWidthsUnshaped( characterString, characterLength, _emSize, scalingFactor, advanceWidthsUnshaped, nullFont, _textFormattingMode, _isSideways ); } } else { GlyphTypeface glyphTypeface = _shapeTypeface.GlyphTypeface; Invariant.Assert(glyphTypeface != null); Invariant.Assert(characterLength > 0); CharacterBufferRange newBuffer = new CharacterBufferRange(characterString, characterLength); MS.Internal.Text.TextInterface.GlyphMetrics[] glyphMetrics = BufferCache.GetGlyphMetrics(characterLength); glyphTypeface.GetGlyphMetricsOptimized(newBuffer, _emSize, _textFormattingMode, _isSideways, glyphMetrics ); double designToEm = _emSize * scalingFactor / glyphTypeface.DesignEmHeight; for (int i = 0; i < characterLength; i++) { advanceWidthsUnshaped[i] = (int)Math.Round(glyphMetrics[i].AdvanceWidth * designToEm); } BufferCache.ReleaseGlyphMetrics(glyphMetrics); } } ////// This is needed to decide whether we should pass a max cluster size to LS. /// We pass a max cluster size to LS to perform line breaking correctly. /// Passing a max cluster size larger than necessary will have impact on perf. /// internal sealed override bool NeedsMaxClusterSize { get { // We will need to pass a max cluster size to LS if: // 1) the script is not Latin (hence more likely to formed into ligature) // 2) or the run contains combining mark or extended characters if (!_textItem.IsLatin || _textItem.HasCombiningMark || _textItem.HasExtendedCharacter ) { return true; } return false; } } ////// Return value indicates whether two runs can shape together /// internal sealed override bool CanShapeTogether( TextShapeableSymbols shapeable ) { TextShapeableCharacters charShape = shapeable as TextShapeableCharacters; if (charShape == null) return false; return _shapeTypeface.Equals(charShape._shapeTypeface) // Extended characters need to be shaped by surrogate shaper. They cannot be shaped together with non-exteneded characters. && (_textItem.HasExtendedCharacter) == (charShape._textItem.HasExtendedCharacter) && _emSize == charShape._emSize && ( _properties.CultureInfo == null ? charShape._properties.CultureInfo == null : _properties.CultureInfo.Equals(charShape._properties.CultureInfo) ) && _nullShape == charShape._nullShape && (_textItem.CanShapeTogether(charShape._textItem)); } ////// Indicate whether run cannot be treated as simple characters because shaping is required. /// /// The following cases use simple rendering without shaping: /// o No _shapeTypeface. This happens in very simple rendering cases. /// o Non-Unicode (i.e. symbol) fonts. /// o When using a device font. /// /// Note that the presence of a device font in _shapeTypeface.DeviceFont implies use of /// a device font in all cases except where digit substitution applies. This special /// case occurs because the cached result per codepoint of TypefaceMap must include the device font /// for non-western digits in order to support device font rendering of the non-Western /// digit Unicode codepoints. The device font is not used however when the non-Western digits /// are displayed as a result of digit substitution from backing store Western digits. /// internal sealed override bool IsShapingRequired { get { return (_shapeTypeface != null) // Can't use shaping without a shape typeface && ( (_shapeTypeface.DeviceFont == null) // Can't use shaping when rendering with a device font || (_textItem.DigitCulture != null)) // -- unless substituting digits && (!IsSymbol); // Can't use shaping for symbol (non-Unicode) fonts } } ////// A Boolean value indicates whether additional info is required for caret positioning /// internal sealed override bool NeedsCaretInfo { get { return (_textItem.HasCombiningMark) || (_textItem.NeedsCaretInfo); } } ////// A Boolean value indicates whether run has extended character /// internal sealed override bool HasExtendedCharacter { get { return _textItem.HasExtendedCharacter; } } ////// Run height /// internal sealed override double Height { get { return _properties.Typeface.LineSpacing(_properties.FontRenderingEmSize, 1, Util.PixelsPerDip, _textFormattingMode); } } ////// Distance from top to baseline /// internal sealed override double Baseline { get { return _properties.Typeface.Baseline(_properties.FontRenderingEmSize, 1, Util.PixelsPerDip, _textFormattingMode); } } ////// Distance from baseline to underline position relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double UnderlinePosition { get { return _properties.Typeface.UnderlinePosition; } } ////// Underline thickness relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double UnderlineThickness { get { return _properties.Typeface.UnderlineThickness; } } ////// Distance from baseline to strike-through position relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double StrikethroughPosition { get { return _properties.Typeface.StrikethroughPosition; } } ////// strike-through thickness relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double StrikethroughThickness { get { return _properties.Typeface.StrikethroughThickness; } } #endregion ////// Whether all characters in this run are non-Unicode character (symbol) /// internal bool IsSymbol { get { if (_shapeTypeface != null) return _shapeTypeface.GlyphTypeface.Symbol; return _properties.Typeface.Symbol; } } internal override GlyphTypeface GlyphTypeFace { get { if (_shapeTypeface != null) return _shapeTypeface.GlyphTypeface; return _properties.Typeface.TryGetGlyphTypeface(); } } ////// Returns maximum possible cluster size for the run. Normally, this /// is 8 characters, but Indic scripts require this to be 15. /// internal const ushort DefaultMaxClusterSize = 8; private const ushort IndicMaxClusterSize = 15; internal sealed override ushort MaxClusterSize { get { if (_textItem.IsIndic) { return IndicMaxClusterSize; } return DefaultMaxClusterSize; } } } } // 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 // // File: TextShapeableCharacters.cs // // Contents: Implementation of text shapeable symbols for characters // // Spec: http://team/sites/Avalon/Specs/Text%20Formatting%20API.doc // // Created: 1-2-2004 Worachai Chaoweeraprasit (wchao) // History: 1-19-2004 garyyyang: Change the class to internal // //----------------------------------------------------------------------- using System; using System.Diagnostics; using System.Globalization; using System.Collections; using System.Collections.Generic; using System.Security; using System.Windows; using System.Windows.Markup; // for XmlLanguage using System.Windows.Media; using MS.Internal; using MS.Internal.FontCache; using MS.Internal.TextFormatting; using MS.Internal.Shaping; using MS.Internal.Text.TextInterface; namespace System.Windows.Media.TextFormatting { ////// A specialized TextShapeableSymbols implemented by TextFormatter to represent /// a collection of glyphs from a physical typeface. /// internal sealed class TextShapeableCharacters : TextShapeableSymbols { private CharacterBufferRange _characterBufferRange; private TextFormattingMode _textFormattingMode; private bool _isSideways; private TextRunProperties _properties; private double _emSize; // after-scaled private ItemProps _textItem; private ShapeTypeface _shapeTypeface; private bool _nullShape; #region Constructors ////// Construct a shapeable characters object /// ////// The shapeTypeface parameter can be null if and only if CheckFastPathNominalGlyphs /// has previously returned true. /// internal TextShapeableCharacters( CharacterBufferRange characterRange, TextRunProperties properties, double emSize, ItemProps textItem, ShapeTypeface shapeTypeface, bool nullShape, TextFormattingMode textFormattingMode, bool isSideways ) { _isSideways = isSideways; _textFormattingMode = textFormattingMode; _characterBufferRange = characterRange; _properties = properties; _emSize = emSize; _textItem = textItem; _shapeTypeface = shapeTypeface; _nullShape = nullShape; } #endregion #region TextRun implementation ////// Character reference /// public sealed override CharacterBufferReference CharacterBufferReference { get { return _characterBufferRange.CharacterBufferReference; } } ////// Character length of the run /// public sealed override int Length { get { return _characterBufferRange.Length; } } ////// A set of properties shared by every characters in the run /// public sealed override TextRunProperties Properties { get { return _properties; } } #endregion #region TextShapeableSymbols implementation ////// Compute a shaped glyph run object from specified glyph-based info /// internal sealed override GlyphRun ComputeShapedGlyphRun( Point origin, char[] characterString, ushort[] clusterMap, ushort[] glyphIndices, IListglyphAdvances, IList glyphOffsets, bool rightToLeft, bool sideways ) { Invariant.Assert(_shapeTypeface != null); Invariant.Assert(glyphIndices != null); // Device fonts are only used through the LS non-glyphed code path. Only when a DigitCulture is set // will a potential device font be ignored and come through shaping. Invariant.Assert(_shapeTypeface.DeviceFont == null || _textItem.DigitCulture != null); bool[] caretStops = null; if ( clusterMap != null && (HasExtendedCharacter || NeedsCaretInfo) ) { caretStops = new bool[clusterMap.Length + 1]; // caret stops at cluster boundaries, the first and the last entries are always set caretStops[0] = true; caretStops[clusterMap.Length] = true; ushort lastGlyph = clusterMap[0]; for (int i = 1; i < clusterMap.Length; i++) { ushort glyph = clusterMap[i]; if (glyph != lastGlyph) { caretStops[i] = true; lastGlyph = glyph; } } } return GlyphRun.TryCreate( _shapeTypeface.GlyphTypeface, (rightToLeft ? 1 : 0), sideways, _emSize, glyphIndices, origin, glyphAdvances, glyphOffsets, characterString, null, clusterMap, caretStops, XmlLanguage.GetLanguage(CultureMapper.GetSpecificCulture(_properties.CultureInfo).IetfLanguageTag), _textFormattingMode ); } private GlyphTypeface GetGlyphTypeface(out bool nullFont) { GlyphTypeface glyphTypeface; if (_shapeTypeface == null) { // We're in the optimized path where the GlyphTypeface depends only // on the Typeface, not on the particular input characters. Typeface typeface = _properties.Typeface; // Get the GlyphTypeface. glyphTypeface = typeface.TryGetGlyphTypeface(); // If Typeface does not specify *any* valid font family, then we use // the GlyphTypeface for Arial but only to display missing glyphs. nullFont = typeface.NullFont; } else { // Font linking has mapped the input to a specific GlyphTypeface. glyphTypeface = _shapeTypeface.GlyphTypeface; // If font linking could not find *any* physical font family, then we // use the GlyphTypeface for Arial but only to display missing glyphs. nullFont = _nullShape; } Invariant.Assert(glyphTypeface != null); return glyphTypeface; } /// /// Compute unshaped glyph run object from the specified character-based info /// internal sealed override GlyphRun ComputeUnshapedGlyphRun( Point origin, char[] characterString, IListcharacterAdvances ) { bool nullFont; GlyphTypeface glyphTypeface = GetGlyphTypeface(out nullFont); Invariant.Assert(glyphTypeface != null); return glyphTypeface.ComputeUnshapedGlyphRun( origin, new CharacterBufferRange( characterString, 0, // offsetToFirstChar characterString.Length ), characterAdvances, _emSize, _properties.FontHintingEmSize, nullFont, CultureMapper.GetSpecificCulture(_properties.CultureInfo), (_shapeTypeface == null || _shapeTypeface.DeviceFont == null) ? null : _shapeTypeface.DeviceFont.Name, _textFormattingMode ); } /// /// Draw glyph run to the drawing surface /// internal sealed override void Draw( DrawingContext drawingContext, Brush foregroundBrush, GlyphRun glyphRun ) { if (drawingContext == null) throw new ArgumentNullException("drawingContext"); glyphRun.EmitBackground(drawingContext, _properties.BackgroundBrush); drawingContext.DrawGlyphRun( foregroundBrush != null ? foregroundBrush : _properties.ForegroundBrush, glyphRun ); } internal override double EmSize { get { return _emSize; } } internal override MS.Internal.Text.TextInterface.ItemProps ItemProps { get { return _textItem; } } ////// Get advance widths of unshaped characters /// ////// Critical: This code deals with pointers and calls SC methods like GetAdvanceWidthsUnshaped /// [SecurityCritical] internal sealed override unsafe void GetAdvanceWidthsUnshaped( char* characterString, int characterLength, double scalingFactor, int* advanceWidthsUnshaped ) { if (!IsShapingRequired) { if ( (_shapeTypeface != null) && (_shapeTypeface.DeviceFont != null)) { // Use device font to compute advance widths _shapeTypeface.DeviceFont.GetAdvanceWidths( characterString, characterLength, _emSize * scalingFactor, advanceWidthsUnshaped ); } else { bool nullFont; GlyphTypeface glyphTypeface = GetGlyphTypeface(out nullFont); Invariant.Assert(glyphTypeface != null); glyphTypeface.GetAdvanceWidthsUnshaped( characterString, characterLength, _emSize, scalingFactor, advanceWidthsUnshaped, nullFont, _textFormattingMode, _isSideways ); } } else { GlyphTypeface glyphTypeface = _shapeTypeface.GlyphTypeface; Invariant.Assert(glyphTypeface != null); Invariant.Assert(characterLength > 0); CharacterBufferRange newBuffer = new CharacterBufferRange(characterString, characterLength); MS.Internal.Text.TextInterface.GlyphMetrics[] glyphMetrics = BufferCache.GetGlyphMetrics(characterLength); glyphTypeface.GetGlyphMetricsOptimized(newBuffer, _emSize, _textFormattingMode, _isSideways, glyphMetrics ); double designToEm = _emSize * scalingFactor / glyphTypeface.DesignEmHeight; for (int i = 0; i < characterLength; i++) { advanceWidthsUnshaped[i] = (int)Math.Round(glyphMetrics[i].AdvanceWidth * designToEm); } BufferCache.ReleaseGlyphMetrics(glyphMetrics); } } ////// This is needed to decide whether we should pass a max cluster size to LS. /// We pass a max cluster size to LS to perform line breaking correctly. /// Passing a max cluster size larger than necessary will have impact on perf. /// internal sealed override bool NeedsMaxClusterSize { get { // We will need to pass a max cluster size to LS if: // 1) the script is not Latin (hence more likely to formed into ligature) // 2) or the run contains combining mark or extended characters if (!_textItem.IsLatin || _textItem.HasCombiningMark || _textItem.HasExtendedCharacter ) { return true; } return false; } } ////// Return value indicates whether two runs can shape together /// internal sealed override bool CanShapeTogether( TextShapeableSymbols shapeable ) { TextShapeableCharacters charShape = shapeable as TextShapeableCharacters; if (charShape == null) return false; return _shapeTypeface.Equals(charShape._shapeTypeface) // Extended characters need to be shaped by surrogate shaper. They cannot be shaped together with non-exteneded characters. && (_textItem.HasExtendedCharacter) == (charShape._textItem.HasExtendedCharacter) && _emSize == charShape._emSize && ( _properties.CultureInfo == null ? charShape._properties.CultureInfo == null : _properties.CultureInfo.Equals(charShape._properties.CultureInfo) ) && _nullShape == charShape._nullShape && (_textItem.CanShapeTogether(charShape._textItem)); } ////// Indicate whether run cannot be treated as simple characters because shaping is required. /// /// The following cases use simple rendering without shaping: /// o No _shapeTypeface. This happens in very simple rendering cases. /// o Non-Unicode (i.e. symbol) fonts. /// o When using a device font. /// /// Note that the presence of a device font in _shapeTypeface.DeviceFont implies use of /// a device font in all cases except where digit substitution applies. This special /// case occurs because the cached result per codepoint of TypefaceMap must include the device font /// for non-western digits in order to support device font rendering of the non-Western /// digit Unicode codepoints. The device font is not used however when the non-Western digits /// are displayed as a result of digit substitution from backing store Western digits. /// internal sealed override bool IsShapingRequired { get { return (_shapeTypeface != null) // Can't use shaping without a shape typeface && ( (_shapeTypeface.DeviceFont == null) // Can't use shaping when rendering with a device font || (_textItem.DigitCulture != null)) // -- unless substituting digits && (!IsSymbol); // Can't use shaping for symbol (non-Unicode) fonts } } ////// A Boolean value indicates whether additional info is required for caret positioning /// internal sealed override bool NeedsCaretInfo { get { return (_textItem.HasCombiningMark) || (_textItem.NeedsCaretInfo); } } ////// A Boolean value indicates whether run has extended character /// internal sealed override bool HasExtendedCharacter { get { return _textItem.HasExtendedCharacter; } } ////// Run height /// internal sealed override double Height { get { return _properties.Typeface.LineSpacing(_properties.FontRenderingEmSize, 1, Util.PixelsPerDip, _textFormattingMode); } } ////// Distance from top to baseline /// internal sealed override double Baseline { get { return _properties.Typeface.Baseline(_properties.FontRenderingEmSize, 1, Util.PixelsPerDip, _textFormattingMode); } } ////// Distance from baseline to underline position relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double UnderlinePosition { get { return _properties.Typeface.UnderlinePosition; } } ////// Underline thickness relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double UnderlineThickness { get { return _properties.Typeface.UnderlineThickness; } } ////// Distance from baseline to strike-through position relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double StrikethroughPosition { get { return _properties.Typeface.StrikethroughPosition; } } ////// strike-through thickness relative to TextRunProperties.FontRenderingEmSize /// internal sealed override double StrikethroughThickness { get { return _properties.Typeface.StrikethroughThickness; } } #endregion ////// Whether all characters in this run are non-Unicode character (symbol) /// internal bool IsSymbol { get { if (_shapeTypeface != null) return _shapeTypeface.GlyphTypeface.Symbol; return _properties.Typeface.Symbol; } } internal override GlyphTypeface GlyphTypeFace { get { if (_shapeTypeface != null) return _shapeTypeface.GlyphTypeface; return _properties.Typeface.TryGetGlyphTypeface(); } } ////// Returns maximum possible cluster size for the run. Normally, this /// is 8 characters, but Indic scripts require this to be 15. /// internal const ushort DefaultMaxClusterSize = 8; private const ushort IndicMaxClusterSize = 15; internal sealed override ushort MaxClusterSize { get { if (_textItem.IsIndic) { return IndicMaxClusterSize; } return DefaultMaxClusterSize; } } } } // 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
- RecognizedPhrase.cs
- GeometryHitTestResult.cs
- LineVisual.cs
- UIAgentAsyncParams.cs
- ItemType.cs
- ByteAnimation.cs
- MessageQueueEnumerator.cs
- RenderData.cs
- InkPresenterAutomationPeer.cs
- HighlightVisual.cs
- SerializerWriterEventHandlers.cs
- DataComponentNameHandler.cs
- TypeConverterAttribute.cs
- XmlWriterTraceListener.cs
- OleDbCommandBuilder.cs
- CalendarDesigner.cs
- CTreeGenerator.cs
- Activity.cs
- ProviderSettingsCollection.cs
- WebControlsSection.cs
- CompilationLock.cs
- TailCallAnalyzer.cs
- XmlParserContext.cs
- DbConnectionInternal.cs
- DoubleAverageAggregationOperator.cs
- XmlRootAttribute.cs
- MembershipSection.cs
- TCPListener.cs
- MSG.cs
- PinnedBufferMemoryStream.cs
- TextStore.cs
- ExeContext.cs
- XPathDocumentIterator.cs
- ExternalFile.cs
- SchemaNames.cs
- MouseActionConverter.cs
- ApplicationInfo.cs
- DiscoveryClientChannelBase.cs
- MatrixAnimationBase.cs
- OdbcCommandBuilder.cs
- InitializationEventAttribute.cs
- LOSFormatter.cs
- SectionUpdates.cs
- Pointer.cs
- ITextView.cs
- LoginName.cs
- SqlCommand.cs
- ProfileElement.cs
- DataGridViewAutoSizeColumnModeEventArgs.cs
- ArrayWithOffset.cs
- Rect3D.cs
- PageTheme.cs
- TransformedBitmap.cs
- XmlDataProvider.cs
- HtmlShimManager.cs
- SortDescription.cs
- HttpCapabilitiesSectionHandler.cs
- SqlError.cs
- ResourceDictionaryCollection.cs
- ThreadPool.cs
- ListMarkerSourceInfo.cs
- StringValidator.cs
- ContentElement.cs
- StrongNameHelpers.cs
- ArraySortHelper.cs
- ContainerParaClient.cs
- StyleTypedPropertyAttribute.cs
- EventMappingSettingsCollection.cs
- DrawItemEvent.cs
- InvalidOleVariantTypeException.cs
- DependencyPropertyHelper.cs
- PtsCache.cs
- ToolboxItemCollection.cs
- PropertyPathWorker.cs
- InheritanceRules.cs
- GlyphsSerializer.cs
- InputReportEventArgs.cs
- GridViewPageEventArgs.cs
- DecoderNLS.cs
- Operators.cs
- SmuggledIUnknown.cs
- DataRow.cs
- NameValueSectionHandler.cs
- PropertyEmitterBase.cs
- RayHitTestParameters.cs
- IgnoreSectionHandler.cs
- StrokeDescriptor.cs
- DataGridViewCellStyleConverter.cs
- WebPermission.cs
- RequestCacheValidator.cs
- SchemaNamespaceManager.cs
- TextServicesCompartmentEventSink.cs
- SqlGatherConsumedAliases.cs
- FilterException.cs
- ConfigurationStrings.cs
- SubMenuStyleCollection.cs
- BaseCollection.cs
- IFlowDocumentViewer.cs
- CharUnicodeInfo.cs
- DispatcherOperation.cs