Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RectangleGeometry.cs
- mansign.cs
- PKCS1MaskGenerationMethod.cs
- HttpCacheParams.cs
- RadialGradientBrush.cs
- RoleService.cs
- SafeHandles.cs
- WebFaultClientMessageInspector.cs
- CharKeyFrameCollection.cs
- SqlUtils.cs
- AxWrapperGen.cs
- ClientBuildManager.cs
- BaseEntityWrapper.cs
- EventSourceCreationData.cs
- ViewGenerator.cs
- GuidelineSet.cs
- SiteMapPath.cs
- ZipPackage.cs
- SimpleTypeResolver.cs
- MonikerProxyAttribute.cs
- HGlobalSafeHandle.cs
- ConnectionPointConverter.cs
- CSharpCodeProvider.cs
- SelectionChangedEventArgs.cs
- DataGridViewCellValidatingEventArgs.cs
- XamlFrame.cs
- ServerIdentity.cs
- XmlDesigner.cs
- ListBoxItem.cs
- QueryCacheEntry.cs
- OdbcConnection.cs
- Label.cs
- TextEditorContextMenu.cs
- ThreadExceptionEvent.cs
- ClusterRegistryConfigurationProvider.cs
- documentsequencetextcontainer.cs
- ConfigXmlCDataSection.cs
- OdbcStatementHandle.cs
- MsiStyleLogWriter.cs
- FormsIdentity.cs
- RegistrationContext.cs
- ComContractElementCollection.cs
- EndpointDispatcher.cs
- XmlCharCheckingReader.cs
- JsonCollectionDataContract.cs
- Int32KeyFrameCollection.cs
- MergeFilterQuery.cs
- RequestDescription.cs
- ProfileSettings.cs
- Keyboard.cs
- PieceNameHelper.cs
- EarlyBoundInfo.cs
- MSAANativeProvider.cs
- PrivilegeNotHeldException.cs
- CodeSnippetStatement.cs
- NamespaceMapping.cs
- ExpandCollapsePattern.cs
- DecoderBestFitFallback.cs
- AsyncResult.cs
- ObjectContext.cs
- QueryableDataSource.cs
- TreeNodeEventArgs.cs
- MimePart.cs
- RawUIStateInputReport.cs
- OdbcCommand.cs
- AnyAllSearchOperator.cs
- ListViewTableRow.cs
- WebPartAuthorizationEventArgs.cs
- StatusBar.cs
- BasicViewGenerator.cs
- BinaryReader.cs
- SqlCacheDependency.cs
- SqlCacheDependencyDatabase.cs
- DataBinding.cs
- XmlCharType.cs
- SecurityValidationBehavior.cs
- FixedSOMElement.cs
- CategoryEditor.cs
- ScriptResourceAttribute.cs
- ComponentConverter.cs
- SafeBitVector32.cs
- XPathDocumentIterator.cs
- DataGridViewCellCancelEventArgs.cs
- SqlReferenceCollection.cs
- SmtpSection.cs
- UITypeEditor.cs
- InvalidCommandTreeException.cs
- SortAction.cs
- TextServicesLoader.cs
- GroupBox.cs
- PageBuildProvider.cs
- DateTimeSerializationSection.cs
- RNGCryptoServiceProvider.cs
- SrgsToken.cs
- __FastResourceComparer.cs
- sqlnorm.cs
- SubordinateTransaction.cs
- ListBoxItemAutomationPeer.cs
- OracleDateTime.cs
- ListViewSortEventArgs.cs