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 / TextFormatting / FormattedTextSymbols.cs / 1 / FormattedTextSymbols.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: // Formatting a single style, single reading direction text symbols // // History: // 08/16/2004 : wchao - Created it // //--------------------------------------------------------------------------- using System; using System.Security; using System.Windows; using System.Windows.Media; using System.Windows.Media.TextFormatting; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using MS.Internal; using MS.Internal.Shaping; namespace MS.Internal.TextFormatting { ////// Formatted form of TextSymbols /// internal sealed class FormattedTextSymbols { private Glyphs[] _glyphs; private bool _rightToLeft; ////// Construct a formatted run /// ////// Critical - this method has unsafe blocks /// Safe - it doesn't expose any critical data /// [SecurityCritical, SecurityTreatAsSafe] public FormattedTextSymbols( GlyphingCache glyphingCache, TextRun textSymbols, bool rightToLeft, double scalingFactor ) { ITextSymbols symbols = textSymbols as ITextSymbols; Debug.Assert(symbols != null); // break down a single text run into pieces IListshapeables = symbols.GetTextShapeableSymbols( glyphingCache, textSymbols.CharacterBufferReference, textSymbols.Length, rightToLeft, null, // cultureInfo null // textModifierScope ); Debug.Assert(shapeables != null && shapeables.Count > 0); _rightToLeft = rightToLeft; _glyphs = new Glyphs[shapeables.Count]; CharacterBuffer charBuffer = textSymbols.CharacterBufferReference.CharacterBuffer; int offsetToFirstChar = textSymbols.CharacterBufferReference.OffsetToFirstChar; int i = 0; int ich = 0; while (i < shapeables.Count) { TextShapeableSymbols current = shapeables[i] as TextShapeableSymbols; Debug.Assert(current != null); int cch = current.Length; int j; // make a separate character buffer for glyphrun persistence char[] charArray = new char[cch]; for (j = 0; j < cch; j++) charArray[j] = charBuffer[offsetToFirstChar + ich + j]; if (current.IsShapingRequired) { ushort[] clusterMap = new ushort[cch]; CharacterShapingProperties[] charProp = new CharacterShapingProperties[cch]; int glyphCount; ushort[] glyphIndices; GlyphShapingProperties[] glyphProp; int[] glyphAdvances; GlyphOffset[] glyphOffsets; // Note that we dont check for the chance of having multiple // shapeables shaped together here since we're dealing with // single-style text. There is virtually no chance to require // for adjacent runs to shape together. We rely on TextSymbols // to reduce duplication of the itemized shapeables for performance. unsafe { fixed (char* fixedCharArray = &charArray[0]) fixed (ushort* fixedClusterMap = &clusterMap[0]) fixed (CharacterShapingProperties* fixedCharProp = &charProp[0]) { glyphIndices = current.GetGlyphs( new CheckedCharPointer(fixedCharArray, cch), cch, ShapingOptions.None, null, // featureSet new CheckedUShortPointer(fixedClusterMap, cch), new CheckedCharacterShapingPropertiesPointer(fixedCharProp,cch), out glyphProp, out glyphCount ); // Shaping is all done in ideal units. // Create int[] and GlyphOffset[] for shaping glyphAdvances = new int[glyphCount]; glyphOffsets = new GlyphOffset[glyphCount]; fixed (ushort* fixedGlyphIndices = &glyphIndices[0]) fixed (GlyphShapingProperties* fixedGlyphProp = &glyphProp[0]) fixed (int* fixedGlyphAdvances = &glyphAdvances[0]) fixed (GlyphOffset * fixedGlyphOffsets = &glyphOffsets[0]) { current.GetGlyphPlacements( new CheckedUShortPointer(fixedGlyphIndices, glyphCount), new CheckedGlyphShapingPropertiesPointer(fixedGlyphProp, glyphCount), glyphCount, new CheckedUShortPointer(fixedClusterMap, cch), new CheckedCharacterShapingPropertiesPointer(fixedCharProp, cch), cch, ShapingOptions.None, null, // featureSet scalingFactor, // format resolution specified per em new CheckedIntPointer(fixedGlyphAdvances, glyphCount), new CheckedGlyphOffsetPointer(fixedGlyphOffsets, glyphCount) ); } } _glyphs[i] = new Glyphs( current, charArray, glyphAdvances, clusterMap, glyphIndices, glyphProp, glyphOffsets, scalingFactor ); } } else { // shaping not required, // bypass glyphing process altogether int[] nominalAdvances = new int[charArray.Length]; unsafe { fixed(char* fixedCharArray = &charArray[0]) fixed(int * fixedNominalAdvances = &nominalAdvances[0]) { current.GetAdvanceWidthsUnshaped( fixedCharArray, cch, scalingFactor, // format resolution specified per em, fixedNominalAdvances ); } } _glyphs[i] = new Glyphs( current, charArray, nominalAdvances, scalingFactor ); } i++; ich += cch; } } /// /// Total formatted width /// public double Width { get { Debug.Assert(_glyphs != null); double width = 0; foreach (Glyphs glyphs in _glyphs) { width += glyphs.Width; } return width; } } ////// Draw all formatted glyphruns /// ///drawing bounding box public Rect Draw( DrawingContext drawingContext, Point currentOrigin ) { Rect inkBoundingBox = Rect.Empty; Debug.Assert(_glyphs != null); foreach (Glyphs glyphs in _glyphs) { GlyphRun glyphRun = glyphs.CreateGlyphRun(currentOrigin, _rightToLeft); Rect boundingBox; if (glyphRun != null) { boundingBox = glyphRun.ComputeInkBoundingBox(); if (drawingContext != null) { // Emit glyph run background. glyphRun.EmitBackground(drawingContext, glyphs.BackgroundBrush); drawingContext.PushGuidelineY1(currentOrigin.Y); try { drawingContext.DrawGlyphRun(glyphs.ForegroundBrush, glyphRun); } finally { drawingContext.Pop(); } } } else { boundingBox = Rect.Empty; } if (!boundingBox.IsEmpty) { // glyph run's ink bounding box is relative to its origin boundingBox.X += glyphRun.BaselineOrigin.X; boundingBox.Y += glyphRun.BaselineOrigin.Y; } // accumulate overall ink bounding box inkBoundingBox.Union(boundingBox); if (_rightToLeft) { currentOrigin.X -= glyphs.Width; } else { currentOrigin.X += glyphs.Width; } } return inkBoundingBox; } ////// All glyph properties used during GlyphRun construction /// ////// We should be able to get rid off this type and just store GlyphRuns /// once GlyphRun gets refactor'd so that it contains no drawing time /// positioning data inside. /// private sealed class Glyphs { private TextShapeableSymbols _shapeable; private char[] _charArray; private ushort[] _clusterMap; private ushort[] _glyphIndices; private GlyphShapingProperties[] _glyphProp; private double[] _glyphAdvances; private IList_glyphOffsets; private double _width; /// /// Construct a nominal description of glyph data /// internal Glyphs( TextShapeableSymbols shapeable, char[] charArray, int[] nominalAdvances, double scalingFactor ) : this( shapeable, charArray, nominalAdvances, null, // clusterMap null, // glyphIndices null, // glyphProp null, // glyphOffsets scalingFactor ) {} ////// Construct a full description of glyph data /// internal Glyphs( TextShapeableSymbols shapeable, char[] charArray, int[] glyphAdvances, ushort[] clusterMap, ushort[] glyphIndices, GlyphShapingProperties[] glyphProp, GlyphOffset[] glyphOffsets, double scalingFactor ) { _shapeable = shapeable; _charArray = charArray; // create double array for glyph run creation, because Shaping is all done in // ideal units. FormattedTextSymbol is used to draw text collapsing symbols // which usually contains very few glyphs. Using double[] and Point[] directly // is more efficient. _glyphAdvances = new double[glyphAdvances.Length]; double ToReal = 1.0 / scalingFactor; for (int i = 0; i < glyphAdvances.Length; i++) { _glyphAdvances[i] = glyphAdvances[i] * ToReal; _width += _glyphAdvances[i]; } if (glyphIndices != null) { _clusterMap = clusterMap; if (glyphOffsets != null) { _glyphOffsets = new PartialArray(new Point[glyphOffsets.Length]); for (int i = 0; i < glyphOffsets.Length; i++) { _glyphOffsets[i] = new Point( glyphOffsets[i].du * ToReal, glyphOffsets[i].dv * ToReal ); } } Debug.Assert(glyphAdvances.Length <= glyphIndices.Length); if (glyphAdvances.Length != glyphIndices.Length) { _glyphIndices = new ushort[glyphAdvances.Length]; _glyphProp = new GlyphShapingProperties[glyphAdvances.Length]; for (int i = 0; i < glyphAdvances.Length; i++) { _glyphIndices[i] = glyphIndices[i]; _glyphProp[i] = glyphProp[i]; } } else { _glyphIndices = glyphIndices; _glyphProp = glyphProp; } } } /// /// Total formatted width /// public double Width { get { return _width; } } ////// Construct a GlyphRun object given the specified drawing origin /// internal GlyphRun CreateGlyphRun( Point currentOrigin, bool rightToLeft ) { if (!_shapeable.IsShapingRequired) { return _shapeable.ComputeUnshapedGlyphRun( currentOrigin, _charArray, _glyphAdvances ); } return _shapeable.ComputeShapedGlyphRun( currentOrigin, _charArray, _clusterMap, _glyphIndices, _glyphProp, _glyphAdvances, _glyphOffsets, rightToLeft, false // sideways not yet supported ); } public Brush ForegroundBrush { get { return _shapeable.Properties.ForegroundBrush; } } public Brush BackgroundBrush { get { return _shapeable.Properties.BackgroundBrush; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: // Formatting a single style, single reading direction text symbols // // History: // 08/16/2004 : wchao - Created it // //--------------------------------------------------------------------------- using System; using System.Security; using System.Windows; using System.Windows.Media; using System.Windows.Media.TextFormatting; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using MS.Internal; using MS.Internal.Shaping; namespace MS.Internal.TextFormatting { ////// Formatted form of TextSymbols /// internal sealed class FormattedTextSymbols { private Glyphs[] _glyphs; private bool _rightToLeft; ////// Construct a formatted run /// ////// Critical - this method has unsafe blocks /// Safe - it doesn't expose any critical data /// [SecurityCritical, SecurityTreatAsSafe] public FormattedTextSymbols( GlyphingCache glyphingCache, TextRun textSymbols, bool rightToLeft, double scalingFactor ) { ITextSymbols symbols = textSymbols as ITextSymbols; Debug.Assert(symbols != null); // break down a single text run into pieces IListshapeables = symbols.GetTextShapeableSymbols( glyphingCache, textSymbols.CharacterBufferReference, textSymbols.Length, rightToLeft, null, // cultureInfo null // textModifierScope ); Debug.Assert(shapeables != null && shapeables.Count > 0); _rightToLeft = rightToLeft; _glyphs = new Glyphs[shapeables.Count]; CharacterBuffer charBuffer = textSymbols.CharacterBufferReference.CharacterBuffer; int offsetToFirstChar = textSymbols.CharacterBufferReference.OffsetToFirstChar; int i = 0; int ich = 0; while (i < shapeables.Count) { TextShapeableSymbols current = shapeables[i] as TextShapeableSymbols; Debug.Assert(current != null); int cch = current.Length; int j; // make a separate character buffer for glyphrun persistence char[] charArray = new char[cch]; for (j = 0; j < cch; j++) charArray[j] = charBuffer[offsetToFirstChar + ich + j]; if (current.IsShapingRequired) { ushort[] clusterMap = new ushort[cch]; CharacterShapingProperties[] charProp = new CharacterShapingProperties[cch]; int glyphCount; ushort[] glyphIndices; GlyphShapingProperties[] glyphProp; int[] glyphAdvances; GlyphOffset[] glyphOffsets; // Note that we dont check for the chance of having multiple // shapeables shaped together here since we're dealing with // single-style text. There is virtually no chance to require // for adjacent runs to shape together. We rely on TextSymbols // to reduce duplication of the itemized shapeables for performance. unsafe { fixed (char* fixedCharArray = &charArray[0]) fixed (ushort* fixedClusterMap = &clusterMap[0]) fixed (CharacterShapingProperties* fixedCharProp = &charProp[0]) { glyphIndices = current.GetGlyphs( new CheckedCharPointer(fixedCharArray, cch), cch, ShapingOptions.None, null, // featureSet new CheckedUShortPointer(fixedClusterMap, cch), new CheckedCharacterShapingPropertiesPointer(fixedCharProp,cch), out glyphProp, out glyphCount ); // Shaping is all done in ideal units. // Create int[] and GlyphOffset[] for shaping glyphAdvances = new int[glyphCount]; glyphOffsets = new GlyphOffset[glyphCount]; fixed (ushort* fixedGlyphIndices = &glyphIndices[0]) fixed (GlyphShapingProperties* fixedGlyphProp = &glyphProp[0]) fixed (int* fixedGlyphAdvances = &glyphAdvances[0]) fixed (GlyphOffset * fixedGlyphOffsets = &glyphOffsets[0]) { current.GetGlyphPlacements( new CheckedUShortPointer(fixedGlyphIndices, glyphCount), new CheckedGlyphShapingPropertiesPointer(fixedGlyphProp, glyphCount), glyphCount, new CheckedUShortPointer(fixedClusterMap, cch), new CheckedCharacterShapingPropertiesPointer(fixedCharProp, cch), cch, ShapingOptions.None, null, // featureSet scalingFactor, // format resolution specified per em new CheckedIntPointer(fixedGlyphAdvances, glyphCount), new CheckedGlyphOffsetPointer(fixedGlyphOffsets, glyphCount) ); } } _glyphs[i] = new Glyphs( current, charArray, glyphAdvances, clusterMap, glyphIndices, glyphProp, glyphOffsets, scalingFactor ); } } else { // shaping not required, // bypass glyphing process altogether int[] nominalAdvances = new int[charArray.Length]; unsafe { fixed(char* fixedCharArray = &charArray[0]) fixed(int * fixedNominalAdvances = &nominalAdvances[0]) { current.GetAdvanceWidthsUnshaped( fixedCharArray, cch, scalingFactor, // format resolution specified per em, fixedNominalAdvances ); } } _glyphs[i] = new Glyphs( current, charArray, nominalAdvances, scalingFactor ); } i++; ich += cch; } } /// /// Total formatted width /// public double Width { get { Debug.Assert(_glyphs != null); double width = 0; foreach (Glyphs glyphs in _glyphs) { width += glyphs.Width; } return width; } } ////// Draw all formatted glyphruns /// ///drawing bounding box public Rect Draw( DrawingContext drawingContext, Point currentOrigin ) { Rect inkBoundingBox = Rect.Empty; Debug.Assert(_glyphs != null); foreach (Glyphs glyphs in _glyphs) { GlyphRun glyphRun = glyphs.CreateGlyphRun(currentOrigin, _rightToLeft); Rect boundingBox; if (glyphRun != null) { boundingBox = glyphRun.ComputeInkBoundingBox(); if (drawingContext != null) { // Emit glyph run background. glyphRun.EmitBackground(drawingContext, glyphs.BackgroundBrush); drawingContext.PushGuidelineY1(currentOrigin.Y); try { drawingContext.DrawGlyphRun(glyphs.ForegroundBrush, glyphRun); } finally { drawingContext.Pop(); } } } else { boundingBox = Rect.Empty; } if (!boundingBox.IsEmpty) { // glyph run's ink bounding box is relative to its origin boundingBox.X += glyphRun.BaselineOrigin.X; boundingBox.Y += glyphRun.BaselineOrigin.Y; } // accumulate overall ink bounding box inkBoundingBox.Union(boundingBox); if (_rightToLeft) { currentOrigin.X -= glyphs.Width; } else { currentOrigin.X += glyphs.Width; } } return inkBoundingBox; } ////// All glyph properties used during GlyphRun construction /// ////// We should be able to get rid off this type and just store GlyphRuns /// once GlyphRun gets refactor'd so that it contains no drawing time /// positioning data inside. /// private sealed class Glyphs { private TextShapeableSymbols _shapeable; private char[] _charArray; private ushort[] _clusterMap; private ushort[] _glyphIndices; private GlyphShapingProperties[] _glyphProp; private double[] _glyphAdvances; private IList_glyphOffsets; private double _width; /// /// Construct a nominal description of glyph data /// internal Glyphs( TextShapeableSymbols shapeable, char[] charArray, int[] nominalAdvances, double scalingFactor ) : this( shapeable, charArray, nominalAdvances, null, // clusterMap null, // glyphIndices null, // glyphProp null, // glyphOffsets scalingFactor ) {} ////// Construct a full description of glyph data /// internal Glyphs( TextShapeableSymbols shapeable, char[] charArray, int[] glyphAdvances, ushort[] clusterMap, ushort[] glyphIndices, GlyphShapingProperties[] glyphProp, GlyphOffset[] glyphOffsets, double scalingFactor ) { _shapeable = shapeable; _charArray = charArray; // create double array for glyph run creation, because Shaping is all done in // ideal units. FormattedTextSymbol is used to draw text collapsing symbols // which usually contains very few glyphs. Using double[] and Point[] directly // is more efficient. _glyphAdvances = new double[glyphAdvances.Length]; double ToReal = 1.0 / scalingFactor; for (int i = 0; i < glyphAdvances.Length; i++) { _glyphAdvances[i] = glyphAdvances[i] * ToReal; _width += _glyphAdvances[i]; } if (glyphIndices != null) { _clusterMap = clusterMap; if (glyphOffsets != null) { _glyphOffsets = new PartialArray(new Point[glyphOffsets.Length]); for (int i = 0; i < glyphOffsets.Length; i++) { _glyphOffsets[i] = new Point( glyphOffsets[i].du * ToReal, glyphOffsets[i].dv * ToReal ); } } Debug.Assert(glyphAdvances.Length <= glyphIndices.Length); if (glyphAdvances.Length != glyphIndices.Length) { _glyphIndices = new ushort[glyphAdvances.Length]; _glyphProp = new GlyphShapingProperties[glyphAdvances.Length]; for (int i = 0; i < glyphAdvances.Length; i++) { _glyphIndices[i] = glyphIndices[i]; _glyphProp[i] = glyphProp[i]; } } else { _glyphIndices = glyphIndices; _glyphProp = glyphProp; } } } /// /// Total formatted width /// public double Width { get { return _width; } } ////// Construct a GlyphRun object given the specified drawing origin /// internal GlyphRun CreateGlyphRun( Point currentOrigin, bool rightToLeft ) { if (!_shapeable.IsShapingRequired) { return _shapeable.ComputeUnshapedGlyphRun( currentOrigin, _charArray, _glyphAdvances ); } return _shapeable.ComputeShapedGlyphRun( currentOrigin, _charArray, _clusterMap, _glyphIndices, _glyphProp, _glyphAdvances, _glyphOffsets, rightToLeft, false // sideways not yet supported ); } public Brush ForegroundBrush { get { return _shapeable.Properties.ForegroundBrush; } } public Brush BackgroundBrush { get { return _shapeable.Properties.BackgroundBrush; } } } } } // 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
- PersonalizableAttribute.cs
- WriteableBitmap.cs
- TypefaceMetricsCache.cs
- CodeAccessPermission.cs
- ModelItemCollection.cs
- DeferredReference.cs
- NamespaceCollection.cs
- EventManager.cs
- PackUriHelper.cs
- DragEvent.cs
- DefaultClaimSet.cs
- PublishLicense.cs
- PassportIdentity.cs
- TargetControlTypeCache.cs
- ByteAnimation.cs
- EllipseGeometry.cs
- ParameterModifier.cs
- TextOutput.cs
- NativeMethods.cs
- SchemaCreator.cs
- RepeatButtonAutomationPeer.cs
- FloaterBaseParaClient.cs
- FixedTextContainer.cs
- RelationshipConstraintValidator.cs
- MapPathBasedVirtualPathProvider.cs
- followingsibling.cs
- EntityViewGenerationAttribute.cs
- infer.cs
- RuntimeConfig.cs
- TextBoxBase.cs
- TraceLevelStore.cs
- SystemWebSectionGroup.cs
- hwndwrapper.cs
- ClientCultureInfo.cs
- X509CertificateClaimSet.cs
- DirectoryGroupQuery.cs
- DecoratedNameAttribute.cs
- ResolveCriteriaApril2005.cs
- TimeIntervalCollection.cs
- ListViewTableRow.cs
- GeometryModel3D.cs
- SqlNotificationEventArgs.cs
- compensatingcollection.cs
- Perspective.cs
- LocationSectionRecord.cs
- ChannelRequirements.cs
- AccessText.cs
- ParallelTimeline.cs
- ObjectAnimationUsingKeyFrames.cs
- TextRangeEditTables.cs
- RowToParametersTransformer.cs
- SvcMapFileSerializer.cs
- RegexCompiler.cs
- ColumnMapVisitor.cs
- BinaryObjectWriter.cs
- DrawingVisual.cs
- ProcessHostServerConfig.cs
- InstanceDescriptor.cs
- WebConfigurationFileMap.cs
- EventManager.cs
- ChangeBlockUndoRecord.cs
- filewebrequest.cs
- SymbolEqualComparer.cs
- DataServiceEntityAttribute.cs
- OrderedEnumerableRowCollection.cs
- DataRelation.cs
- WebPartAuthorizationEventArgs.cs
- NoneExcludedImageIndexConverter.cs
- DialogResultConverter.cs
- EnlistmentState.cs
- CrossContextChannel.cs
- IconBitmapDecoder.cs
- EventLogQuery.cs
- MailMessageEventArgs.cs
- SolidColorBrush.cs
- MouseGestureConverter.cs
- XPathQilFactory.cs
- XhtmlBasicControlAdapter.cs
- TransactionFlowBindingElement.cs
- QilPatternVisitor.cs
- DependencySource.cs
- HtmlInputFile.cs
- ProviderSettingsCollection.cs
- WindowAutomationPeer.cs
- BindingMemberInfo.cs
- ServiceMetadataBehavior.cs
- HttpMethodConstraint.cs
- Int64Converter.cs
- StreamInfo.cs
- ControlPropertyNameConverter.cs
- Binding.cs
- BrowserCapabilitiesCodeGenerator.cs
- TabRenderer.cs
- AccessibilityHelperForXpWin2k3.cs
- UpdatePanelControlTrigger.cs
- SafeSecurityHandles.cs
- _NegotiateClient.cs
- DataTableNewRowEvent.cs
- Unit.cs
- Peer.cs