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
- ToolStripPanelCell.cs
- AdornerHitTestResult.cs
- ComponentConverter.cs
- DoubleCollectionValueSerializer.cs
- ZipIOBlockManager.cs
- _UncName.cs
- TransformConverter.cs
- StyleHelper.cs
- Vector3DKeyFrameCollection.cs
- OutputCacheSettingsSection.cs
- BuildDependencySet.cs
- HebrewNumber.cs
- CaseInsensitiveOrdinalStringComparer.cs
- AttributeAction.cs
- SelectionRange.cs
- Expression.cs
- BorderGapMaskConverter.cs
- ReflectionServiceProvider.cs
- datacache.cs
- MULTI_QI.cs
- MediaSystem.cs
- RawStylusInput.cs
- DateTimeFormat.cs
- HttpStreamMessageEncoderFactory.cs
- AngleUtil.cs
- HierarchicalDataBoundControl.cs
- FlowLayoutSettings.cs
- DataSvcMapFileSerializer.cs
- TreeNodeBindingCollection.cs
- TraceUtility.cs
- SafeNativeMethodsMilCoreApi.cs
- HtmlTernaryTree.cs
- StorageSetMapping.cs
- CountdownEvent.cs
- HandlerBase.cs
- DropShadowBitmapEffect.cs
- BuildProviderAppliesToAttribute.cs
- CachedFontFamily.cs
- Error.cs
- GCHandleCookieTable.cs
- CustomValidator.cs
- CodeCatchClauseCollection.cs
- EntityDataSourceDesignerHelper.cs
- SerialStream.cs
- SelectionListComponentEditor.cs
- XamlPointCollectionSerializer.cs
- EncryptedKey.cs
- KeyTime.cs
- FixedHyperLink.cs
- ValidatorUtils.cs
- OracleEncoding.cs
- TextRunTypographyProperties.cs
- TextBlock.cs
- EntityCommandDefinition.cs
- Quaternion.cs
- XmlRawWriter.cs
- QilExpression.cs
- FixedSOMPageElement.cs
- ColumnResizeAdorner.cs
- DbConnectionPoolGroupProviderInfo.cs
- GZipStream.cs
- OleAutBinder.cs
- PixelFormats.cs
- ReadWriteObjectLock.cs
- RepeatEnumerable.cs
- IPEndPointCollection.cs
- GlyphsSerializer.cs
- ProgressiveCrcCalculatingStream.cs
- StrongNameHelpers.cs
- CompModSwitches.cs
- AuthenticationServiceManager.cs
- ObjectListDataBindEventArgs.cs
- WebOperationContext.cs
- UnsafeNativeMethods.cs
- PreservationFileWriter.cs
- SystemColors.cs
- UnmanagedHandle.cs
- TrackingMemoryStream.cs
- CommonDialog.cs
- BindingBase.cs
- LayoutTableCell.cs
- Rights.cs
- BaseCodeDomTreeGenerator.cs
- BinaryFormatterWriter.cs
- TdsParserSafeHandles.cs
- IISUnsafeMethods.cs
- TPLETWProvider.cs
- OleDragDropHandler.cs
- TypeNameParser.cs
- Rect3D.cs
- SendMailErrorEventArgs.cs
- ConfigurationLockCollection.cs
- FillErrorEventArgs.cs
- EntityKey.cs
- CommonObjectSecurity.cs
- StringFormat.cs
- SqlConnectionStringBuilder.cs
- ComponentDesigner.cs
- DataBindingCollection.cs
- CodeTypeOfExpression.cs