Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / 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 TextSpan GetPrecedingText(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 TextSpan GetPrecedingText(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
- JulianCalendar.cs
- LocatorGroup.cs
- RefType.cs
- KerberosReceiverSecurityToken.cs
- NotImplementedException.cs
- ConfigurationPermission.cs
- BinaryMessageFormatter.cs
- MetadataSource.cs
- SoapEnumAttribute.cs
- XmlValueConverter.cs
- SoapMessage.cs
- SqlTypeConverter.cs
- ContentPlaceHolder.cs
- ControlUtil.cs
- CacheEntry.cs
- DuplexChannelBinder.cs
- OperationBehaviorAttribute.cs
- XhtmlBasicFormAdapter.cs
- printdlgexmarshaler.cs
- OletxTransactionManager.cs
- StreamHelper.cs
- MediaPlayer.cs
- TiffBitmapEncoder.cs
- TextModifier.cs
- CaseInsensitiveComparer.cs
- SerTrace.cs
- OLEDB_Enum.cs
- WebPartEditorOkVerb.cs
- EntityDataSourceReferenceGroup.cs
- Function.cs
- RolePrincipal.cs
- ImpersonationContext.cs
- MetaData.cs
- ObjectConverter.cs
- ToolTip.cs
- DataTablePropertyDescriptor.cs
- SoundPlayerAction.cs
- Unit.cs
- HitTestResult.cs
- TransportSecurityHelpers.cs
- ActionNotSupportedException.cs
- DefaultBinder.cs
- Style.cs
- Parameter.cs
- _ConnectStream.cs
- HttpModuleAction.cs
- IdentitySection.cs
- RuntimeResourceSet.cs
- ConfigXmlDocument.cs
- TrustVersion.cs
- HelpProvider.cs
- DesignerResources.cs
- SmtpDigestAuthenticationModule.cs
- TextServicesProperty.cs
- UserControlAutomationPeer.cs
- WsatConfiguration.cs
- IncrementalCompileAnalyzer.cs
- CellQuery.cs
- OptimizerPatterns.cs
- DynamicDiscoSearcher.cs
- GuidelineSet.cs
- ProtocolElement.cs
- SrgsElementFactoryCompiler.cs
- ViewSimplifier.cs
- KeyValueConfigurationCollection.cs
- ToolboxBitmapAttribute.cs
- InstanceStoreQueryResult.cs
- HierarchicalDataSourceControl.cs
- PersonalizationProvider.cs
- CounterCreationDataCollection.cs
- BindableTemplateBuilder.cs
- DataControlPagerLinkButton.cs
- ConvertTextFrag.cs
- GenericRootAutomationPeer.cs
- cookiecontainer.cs
- Win32Exception.cs
- VectorAnimation.cs
- ListenerAdapterBase.cs
- AbstractDataSvcMapFileLoader.cs
- UnmanagedBitmapWrapper.cs
- SetStoryboardSpeedRatio.cs
- ScriptDescriptor.cs
- bidPrivateBase.cs
- ResourceExpressionBuilder.cs
- CallbackValidatorAttribute.cs
- InkCanvas.cs
- ParameterReplacerVisitor.cs
- IOException.cs
- PropertyNames.cs
- FieldNameLookup.cs
- FormsAuthentication.cs
- DirtyTextRange.cs
- WebPartCatalogAddVerb.cs
- BackgroundFormatInfo.cs
- WebPartUserCapability.cs
- XMLDiffLoader.cs
- ZipArchive.cs
- SafeBitVector32.cs
- BrowserInteropHelper.cs
- ComponentChangedEvent.cs