Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / MS / Internal / PtsHost / linebase.cs / 1 / linebase.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // File: LineBase.cs // // Description: Text line formatter. // // History: // 02/07/2005 : ghermann - Split from Line.cs // //--------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.Text; using MS.Internal.Documents; using MS.Internal.PtsHost.UnsafeNativeMethods; #pragma warning disable 1634, 1691 // avoid generating warnings about unknown // message numbers and unknown pragmas for PRESharp contol namespace MS.Internal.PtsHost { internal abstract class LineBase : UnmanagedHandle { internal LineBase(BaseParaClient paraClient) : base(paraClient.PtsContext) { _paraClient = paraClient; } // ----------------------------------------------------------------- // // TextSource Implementation // // ----------------------------------------------------------------- #region TextSource Implementation ////// Get a text run at specified text source position. /// /// /// dcp of specified position relative to start of line /// internal abstract TextRun GetTextRun(int dcp); ////// Get text immediately before specified text source position. /// /// /// dcp of specified position relative to start of line /// internal abstract TextSpanGetPrecedingText(int dcp); /// /// Get Text effect index from text source character index /// /// /// dcp of specified position relative to start of line /// internal abstract int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int dcp); #endregion TextSource Implementation //-------------------------------------------------------------------- // // Protected Methods // //------------------------------------------------------------------- #region Protected Methods ////// Fetch the next run at text position. /// /// /// Current position in text array /// ///protected TextRun HandleText(StaticTextPointer position) { DependencyObject element; StaticTextPointer endOfRunPosition; Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text, "TextPointer does not point to characters."); if (position.Parent != null) { element = position.Parent; } else { element = _paraClient.Paragraph.Element; } // Extract the aggregated properties into something that the textrun can use. // TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */); // Calculate the end of the run by finding either: // a) the next intersection of highlight ranges, or // b) the natural end of this textrun endOfRunPosition = position.TextContainer.Highlights.GetNextPropertyChangePosition(position, LogicalDirection.Forward); // Clamp the text run at an arbitrary limit, so we don't make // an unbounded allocation. if (position.GetOffsetToPosition(endOfRunPosition) > 4096) { endOfRunPosition = position.CreatePointer(4096); } // Get character buffer for the text run. char[] textBuffer = new char[position.GetOffsetToPosition(endOfRunPosition)]; // Copy characters from text run into buffer. Note the actual number of characters copied, // which may be different than the buffer's length. Buffer length only specifies the maximum // number of characters int charactersCopied = position.GetTextInRun(LogicalDirection.Forward, textBuffer, 0, textBuffer.Length); // Create text run using the actual number of characters copied return new TextCharacters(textBuffer, 0, charactersCopied, textProps); } /// /// Return next TextRun at element edge start position /// /// /// Current position in text array /// protected TextRun HandleElementStartEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge."); // TextRun run = null; TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Cannot use ITextContainer that does not provide TextElement instances."); Invariant.Assert(!(element is Block), "We do not expect any Blocks inside Paragraphs"); // Treat figure and floaters as special hidden runs. if (element is Figure || element is Floater) { // Get the length of the element int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); // Create special hidden run. run = new FloatingRun(cch, element is Figure); if (element is Figure) { _hasFigures = true; } else { _hasFloaters = true; } } else if (element is LineBreak) { int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); run = new LineBreakRun(cch, PTS.FSFLRES.fsflrSoftBreak); } else if (element.IsEmpty) { // Empty TextElement should affect line metrics. // TextFormatter does not support this feature right now, so as workaround // TextRun with ZERO WIDTH NO-BREAK SPACE is used. TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */); char[] textBuffer = new char[_elementEdgeCharacterLength * 2]; // Assert that _elementEdgeCharacterLength is 1 before we use hard-coded indices Invariant.Assert(_elementEdgeCharacterLength == 1, "Expected value of _elementEdgeCharacterLength is 1"); textBuffer[0] = (char)0xFEFF; textBuffer[1] = (char)0xFEFF; run = new TextCharacters(textBuffer, 0, textBuffer.Length, textProps); } else { Inline inline = (Inline) element; DependencyObject parent = inline.Parent; FlowDirection inlineFlowDirection = inline.FlowDirection; FlowDirection parentFlowDirection = inlineFlowDirection; TextDecorationCollection inlineTextDecorations = DynamicPropertyReader.GetTextDecorations(inline); if(parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inlineFlowDirection != parentFlowDirection) { // Inline's flow direction is different from its parent. Need to create new TextSpanModifier with flow direction if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextSpanModifier( _elementEdgeCharacterLength, null, null, inlineFlowDirection ); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground, inlineFlowDirection ); } } else { if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground ); } } } return run; } ////// Fetch the next run at element end edge position. /// ElementEndEdge; we can have 2 possibilities: /// (1) Close edge of element associated with the text paragraph, /// create synthetic LineBreak run to end the current line. /// (2) End of inline element, hide CloseEdge character and continue /// /// /// Position in current text array protected TextRun HandleElementEndEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); TextRun run; if (position.Parent == _paraClient.Paragraph.Element) { // (1) Close edge of element associated with the text paragraph, // create synthetic LineBreak run to end the current line. run = new ParagraphBreakRun(_syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); } else { TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Element should be here."); Inline inline = (Inline) element; DependencyObject parent = inline.Parent; FlowDirection parentFlowDirection = inline.FlowDirection; if(parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inline.FlowDirection != parentFlowDirection) { run = new TextEndOfSegment(_elementEdgeCharacterLength); } else { TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (textDecorations == null || textDecorations.Count == 0) { // (2) End of inline element, hide CloseEdge character and continue run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextEndOfSegment(_elementEdgeCharacterLength); } } } return run; } ////// Fetch the next run at embedded object position. /// /// /// Character offset of this run. /// /// /// Current position in the text array. /// protected TextRun HandleEmbeddedObject(int dcp, StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); TextRun run = null; DependencyObject embeddedObject = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; if (embeddedObject is UIElement) { // Extract the aggregated properties into something that the textrun can use. TextRunProperties textProps = new TextProperties(embeddedObject, position, true /* inline objects */, true /* get background */); // Create inline object run. run = new InlineObjectRun(TextContainerHelper.EmbeddedObjectLength, (UIElement)embeddedObject, textProps, _paraClient.Paragraph as TextParagraph); } else { // If the embedded object is of an unknown type, treat it as hidden content. run = new TextHidden(TextContainerHelper.EmbeddedObjectLength); } return run; } #endregion Protected Methods #region Internal Methods ////// Synthetic character length. /// internal static int SyntheticCharacterLength { get { return _syntheticCharacterLength; } } ////// Returns true if any figure runs have been handled by this text source - Only valid after line is formatted. /// internal bool HasFigures { get { return _hasFigures; } } ////// Returns true if any floater runs have been handled by this text source - Only valid after line is formatted. /// internal bool HasFloaters { get { return _hasFloaters; } } #endregion Internal Methods #region Protected Fields ////// Owner of the line /// protected readonly BaseParaClient _paraClient; ////// Has any figures? /// protected bool _hasFigures; ////// Has any floaters? /// protected bool _hasFloaters; protected static int _syntheticCharacterLength = 1; ////// Element edge character length. /// protected static int _elementEdgeCharacterLength = 1; #endregion Protected Fields } } #pragma warning enable 1634, 1691 // 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. // // File: LineBase.cs // // Description: Text line formatter. // // History: // 02/07/2005 : ghermann - Split from Line.cs // //--------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.Text; using MS.Internal.Documents; using MS.Internal.PtsHost.UnsafeNativeMethods; #pragma warning disable 1634, 1691 // avoid generating warnings about unknown // message numbers and unknown pragmas for PRESharp contol namespace MS.Internal.PtsHost { internal abstract class LineBase : UnmanagedHandle { internal LineBase(BaseParaClient paraClient) : base(paraClient.PtsContext) { _paraClient = paraClient; } // ----------------------------------------------------------------- // // TextSource Implementation // // ----------------------------------------------------------------- #region TextSource Implementation /// /// Get a text run at specified text source position. /// /// /// dcp of specified position relative to start of line /// internal abstract TextRun GetTextRun(int dcp); ////// Get text immediately before specified text source position. /// /// /// dcp of specified position relative to start of line /// internal abstract TextSpanGetPrecedingText(int dcp); /// /// Get Text effect index from text source character index /// /// /// dcp of specified position relative to start of line /// internal abstract int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int dcp); #endregion TextSource Implementation //-------------------------------------------------------------------- // // Protected Methods // //------------------------------------------------------------------- #region Protected Methods ////// Fetch the next run at text position. /// /// /// Current position in text array /// ///protected TextRun HandleText(StaticTextPointer position) { DependencyObject element; StaticTextPointer endOfRunPosition; Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text, "TextPointer does not point to characters."); if (position.Parent != null) { element = position.Parent; } else { element = _paraClient.Paragraph.Element; } // Extract the aggregated properties into something that the textrun can use. // TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */); // Calculate the end of the run by finding either: // a) the next intersection of highlight ranges, or // b) the natural end of this textrun endOfRunPosition = position.TextContainer.Highlights.GetNextPropertyChangePosition(position, LogicalDirection.Forward); // Clamp the text run at an arbitrary limit, so we don't make // an unbounded allocation. if (position.GetOffsetToPosition(endOfRunPosition) > 4096) { endOfRunPosition = position.CreatePointer(4096); } // Get character buffer for the text run. char[] textBuffer = new char[position.GetOffsetToPosition(endOfRunPosition)]; // Copy characters from text run into buffer. Note the actual number of characters copied, // which may be different than the buffer's length. Buffer length only specifies the maximum // number of characters int charactersCopied = position.GetTextInRun(LogicalDirection.Forward, textBuffer, 0, textBuffer.Length); // Create text run using the actual number of characters copied return new TextCharacters(textBuffer, 0, charactersCopied, textProps); } /// /// Return next TextRun at element edge start position /// /// /// Current position in text array /// protected TextRun HandleElementStartEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart, "TextPointer does not point to element start edge."); // TextRun run = null; TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Cannot use ITextContainer that does not provide TextElement instances."); Invariant.Assert(!(element is Block), "We do not expect any Blocks inside Paragraphs"); // Treat figure and floaters as special hidden runs. if (element is Figure || element is Floater) { // Get the length of the element int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); // Create special hidden run. run = new FloatingRun(cch, element is Figure); if (element is Figure) { _hasFigures = true; } else { _hasFloaters = true; } } else if (element is LineBreak) { int cch = TextContainerHelper.GetElementLength(_paraClient.Paragraph.StructuralCache.TextContainer, element); run = new LineBreakRun(cch, PTS.FSFLRES.fsflrSoftBreak); } else if (element.IsEmpty) { // Empty TextElement should affect line metrics. // TextFormatter does not support this feature right now, so as workaround // TextRun with ZERO WIDTH NO-BREAK SPACE is used. TextProperties textProps = new TextProperties(element, position, false /* inline objects */, true /* get background */); char[] textBuffer = new char[_elementEdgeCharacterLength * 2]; // Assert that _elementEdgeCharacterLength is 1 before we use hard-coded indices Invariant.Assert(_elementEdgeCharacterLength == 1, "Expected value of _elementEdgeCharacterLength is 1"); textBuffer[0] = (char)0xFEFF; textBuffer[1] = (char)0xFEFF; run = new TextCharacters(textBuffer, 0, textBuffer.Length, textProps); } else { Inline inline = (Inline) element; DependencyObject parent = inline.Parent; FlowDirection inlineFlowDirection = inline.FlowDirection; FlowDirection parentFlowDirection = inlineFlowDirection; TextDecorationCollection inlineTextDecorations = DynamicPropertyReader.GetTextDecorations(inline); if(parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inlineFlowDirection != parentFlowDirection) { // Inline's flow direction is different from its parent. Need to create new TextSpanModifier with flow direction if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextSpanModifier( _elementEdgeCharacterLength, null, null, inlineFlowDirection ); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground, inlineFlowDirection ); } } else { if (inlineTextDecorations == null || inlineTextDecorations.Count == 0) { run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextSpanModifier( _elementEdgeCharacterLength, inlineTextDecorations, inline.Foreground ); } } } return run; } ////// Fetch the next run at element end edge position. /// ElementEndEdge; we can have 2 possibilities: /// (1) Close edge of element associated with the text paragraph, /// create synthetic LineBreak run to end the current line. /// (2) End of inline element, hide CloseEdge character and continue /// /// /// Position in current text array protected TextRun HandleElementEndEdge(StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd, "TextPointer does not point to element end edge."); TextRun run; if (position.Parent == _paraClient.Paragraph.Element) { // (1) Close edge of element associated with the text paragraph, // create synthetic LineBreak run to end the current line. run = new ParagraphBreakRun(_syntheticCharacterLength, PTS.FSFLRES.fsflrEndOfParagraph); } else { TextElement element = (TextElement)position.GetAdjacentElement(LogicalDirection.Forward); Debug.Assert(element != null, "Element should be here."); Inline inline = (Inline) element; DependencyObject parent = inline.Parent; FlowDirection parentFlowDirection = inline.FlowDirection; if(parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } if (inline.FlowDirection != parentFlowDirection) { run = new TextEndOfSegment(_elementEdgeCharacterLength); } else { TextDecorationCollection textDecorations = DynamicPropertyReader.GetTextDecorations(inline); if (textDecorations == null || textDecorations.Count == 0) { // (2) End of inline element, hide CloseEdge character and continue run = new TextHidden(_elementEdgeCharacterLength); } else { run = new TextEndOfSegment(_elementEdgeCharacterLength); } } } return run; } ////// Fetch the next run at embedded object position. /// /// /// Character offset of this run. /// /// /// Current position in the text array. /// protected TextRun HandleEmbeddedObject(int dcp, StaticTextPointer position) { Invariant.Assert(position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement, "TextPointer does not point to embedded object."); TextRun run = null; DependencyObject embeddedObject = position.GetAdjacentElement(LogicalDirection.Forward) as DependencyObject; if (embeddedObject is UIElement) { // Extract the aggregated properties into something that the textrun can use. TextRunProperties textProps = new TextProperties(embeddedObject, position, true /* inline objects */, true /* get background */); // Create inline object run. run = new InlineObjectRun(TextContainerHelper.EmbeddedObjectLength, (UIElement)embeddedObject, textProps, _paraClient.Paragraph as TextParagraph); } else { // If the embedded object is of an unknown type, treat it as hidden content. run = new TextHidden(TextContainerHelper.EmbeddedObjectLength); } return run; } #endregion Protected Methods #region Internal Methods ////// Synthetic character length. /// internal static int SyntheticCharacterLength { get { return _syntheticCharacterLength; } } ////// Returns true if any figure runs have been handled by this text source - Only valid after line is formatted. /// internal bool HasFigures { get { return _hasFigures; } } ////// Returns true if any floater runs have been handled by this text source - Only valid after line is formatted. /// internal bool HasFloaters { get { return _hasFloaters; } } #endregion Internal Methods #region Protected Fields ////// Owner of the line /// protected readonly BaseParaClient _paraClient; ////// Has any figures? /// protected bool _hasFigures; ////// Has any floaters? /// protected bool _hasFloaters; protected static int _syntheticCharacterLength = 1; ////// Element edge character length. /// protected static int _elementEdgeCharacterLength = 1; #endregion Protected Fields } } #pragma warning enable 1634, 1691 // 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
- Queue.cs
- InkCollectionBehavior.cs
- ResumeStoryboard.cs
- MappingItemCollection.cs
- XmlSchemaIdentityConstraint.cs
- ColumnResizeAdorner.cs
- ProgramNode.cs
- Variable.cs
- QuaternionIndependentAnimationStorage.cs
- MenuBase.cs
- XsdBuildProvider.cs
- DocumentReferenceCollection.cs
- OrthographicCamera.cs
- TimeStampChecker.cs
- ButtonRenderer.cs
- ItemContainerProviderWrapper.cs
- XmlQueryTypeFactory.cs
- __Filters.cs
- WindowPatternIdentifiers.cs
- FileFormatException.cs
- SpeakCompletedEventArgs.cs
- EmissiveMaterial.cs
- SimpleRecyclingCache.cs
- _NativeSSPI.cs
- ThreadStartException.cs
- TextEditorTyping.cs
- AutoResizedEvent.cs
- EndpointInfo.cs
- WinFormsSecurity.cs
- DbProviderServices.cs
- CodeParameterDeclarationExpression.cs
- Error.cs
- ComEventsHelper.cs
- ToolStripGripRenderEventArgs.cs
- PassportAuthenticationEventArgs.cs
- MailHeaderInfo.cs
- WSTrustDec2005.cs
- Peer.cs
- categoryentry.cs
- WmlImageAdapter.cs
- ImageMap.cs
- Win32KeyboardDevice.cs
- ADMembershipUser.cs
- storagemappingitemcollection.viewdictionary.cs
- PageParser.cs
- AnimationLayer.cs
- SchemaTableOptionalColumn.cs
- HtmlShim.cs
- RC2.cs
- TypeInitializationException.cs
- DesignerToolStripControlHost.cs
- KnownIds.cs
- DataGridViewButtonCell.cs
- CompilerGlobalScopeAttribute.cs
- SqlFunctionAttribute.cs
- ReceiveSecurityHeader.cs
- EnumMemberAttribute.cs
- CustomTrackingQuery.cs
- VariableModifiersHelper.cs
- X509Certificate.cs
- ServiceModelPerformanceCounters.cs
- X509IssuerSerialKeyIdentifierClause.cs
- LineMetrics.cs
- SafeCoTaskMem.cs
- EmptyEnumerable.cs
- AssociationTypeEmitter.cs
- XmlSchemaCompilationSettings.cs
- TargetException.cs
- listitem.cs
- ByteAnimation.cs
- XPathSingletonIterator.cs
- ClassValidator.cs
- CheckPair.cs
- Row.cs
- SqlConnectionPoolGroupProviderInfo.cs
- SBCSCodePageEncoding.cs
- CalendarButton.cs
- CustomValidator.cs
- StructuredTypeEmitter.cs
- BindingCompleteEventArgs.cs
- DataGridCell.cs
- CommittableTransaction.cs
- PieceNameHelper.cs
- HttpCacheVary.cs
- URLMembershipCondition.cs
- PageEventArgs.cs
- HWStack.cs
- CryptoKeySecurity.cs
- StringConcat.cs
- StyleCollectionEditor.cs
- FrugalMap.cs
- DataControlLinkButton.cs
- HtmlDocument.cs
- coordinator.cs
- NameValuePermission.cs
- ProcessModelSection.cs
- GenericQueueSurrogate.cs
- ListControlBoundActionList.cs
- CounterCreationData.cs
- querybuilder.cs