Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / PtsHost / linebase.cs / 1305600 / 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 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)0x200B; textBuffer[1] = (char)0x200B; 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 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)0x200B; textBuffer[1] = (char)0x200B; 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
- TableMethodGenerator.cs
- XPathDocumentBuilder.cs
- DrawListViewColumnHeaderEventArgs.cs
- WebSysDescriptionAttribute.cs
- figurelengthconverter.cs
- RunInstallerAttribute.cs
- ManagedWndProcTracker.cs
- control.ime.cs
- FormViewCommandEventArgs.cs
- NonceToken.cs
- ChildrenQuery.cs
- SafeNativeMethods.cs
- IHttpResponseInternal.cs
- HotCommands.cs
- ContentFileHelper.cs
- DecimalStorage.cs
- Instrumentation.cs
- TypedDataSourceCodeGenerator.cs
- UserNameSecurityTokenAuthenticator.cs
- COM2TypeInfoProcessor.cs
- EnumerableCollectionView.cs
- _BasicClient.cs
- GridViewEditEventArgs.cs
- AuditLog.cs
- XmlUtil.cs
- EventMappingSettings.cs
- Command.cs
- ClickablePoint.cs
- DataGrid.cs
- ParentQuery.cs
- CollectionsUtil.cs
- GrammarBuilderRuleRef.cs
- FacetChecker.cs
- BinaryWriter.cs
- RouteCollection.cs
- ScriptManagerProxy.cs
- TracePayload.cs
- MD5CryptoServiceProvider.cs
- DataReaderContainer.cs
- CodeAttributeDeclarationCollection.cs
- SqlUserDefinedAggregateAttribute.cs
- RemoteAsymmetricSignatureFormatter.cs
- CodeAccessPermission.cs
- StorageEntityTypeMapping.cs
- FunctionOverloadResolver.cs
- CacheMemory.cs
- PasswordTextContainer.cs
- NullableIntMinMaxAggregationOperator.cs
- PrefixQName.cs
- CharEntityEncoderFallback.cs
- ComponentGlyph.cs
- WebPartConnectionsCancelEventArgs.cs
- TreeViewImageIndexConverter.cs
- NotSupportedException.cs
- DataGridLinkButton.cs
- CancellationTokenRegistration.cs
- ClockController.cs
- CounterCreationDataConverter.cs
- MarshalByValueComponent.cs
- CellTreeNode.cs
- SplayTreeNode.cs
- ItemCollection.cs
- RadioButtonRenderer.cs
- SuppressMessageAttribute.cs
- LambdaCompiler.Lambda.cs
- Axis.cs
- KeyedByTypeCollection.cs
- DbProviderConfigurationHandler.cs
- ContainerFilterService.cs
- EntitySqlQueryState.cs
- CellParagraph.cs
- DataTransferEventArgs.cs
- ConfigsHelper.cs
- GridViewCommandEventArgs.cs
- EdmType.cs
- VectorCollectionConverter.cs
- XmlSerializerFaultFormatter.cs
- SizeF.cs
- XPathNavigatorKeyComparer.cs
- RawStylusInputCustomData.cs
- SqlProfileProvider.cs
- ColumnClickEvent.cs
- BooleanSwitch.cs
- SqlGatherConsumedAliases.cs
- DataGridSortCommandEventArgs.cs
- ExtenderProvidedPropertyAttribute.cs
- HostnameComparisonMode.cs
- NamedPermissionSet.cs
- HybridDictionary.cs
- BinaryNode.cs
- DNS.cs
- FileDialogPermission.cs
- RuntimeEnvironment.cs
- PropertyInformationCollection.cs
- LinkedList.cs
- XmlElementCollection.cs
- BinaryNode.cs
- DataGridViewColumn.cs
- BindingsCollection.cs
- BaseWebProxyFinder.cs