Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Text / Line.cs / 1305600 / Line.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// File: Line.cs
//
// Description: Text line formatter.
//
// History:
// 04/25/2003 : [....] - moving from Avalon branch.
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using MS.Internal.PtsHost;
namespace MS.Internal.Text
{
// ---------------------------------------------------------------------
// Text line formatter.
// ---------------------------------------------------------------------
internal abstract class Line : TextSource, IDisposable
{
// ------------------------------------------------------------------
//
// IDisposable Implementation
//
// -----------------------------------------------------------------
#region IDisposable Implementation
// ------------------------------------------------------------------
// Free all resources associated with the line. Prepare it for reuse.
// ------------------------------------------------------------------
public void Dispose()
{
// Dispose text line
if (_line != null)
{
_line.Dispose();
_line = null;
}
GC.SuppressFinalize(this);
}
#endregion IDisposable Implementation
//-------------------------------------------------------------------
//
// Internal Methods
//
//--------------------------------------------------------------------
#region Internal Methods
// -----------------------------------------------------------------
// Constructor.
//
// owner - owner of the line.
// -----------------------------------------------------------------
internal Line(System.Windows.Controls.TextBlock owner)
{
_owner = owner;
_textAlignment = owner.TextAlignment;
_showParagraphEllipsis = false;
_wrappingWidth = _owner.RenderSize.Width;
}
// -----------------------------------------------------------------
// Create and format text line.
//
// lineStartIndex - index of the first character in the line
// width - wrapping width of the line
// lineProperties - properties of the line
// textRunCache - run cache used by text formatter
// showParagraphEllipsis - true if paragraph ellipsis is shown
// at the end of the line
// ------------------------------------------------------------------
internal void Format(int dcp, double width, TextParagraphProperties lineProperties, TextLineBreak textLineBreak, TextRunCache textRunCache, bool showParagraphEllipsis)
{
#if TEXTPANELLAYOUTDEBUG
TextPanelDebug.IncrementCounter("Line.Format", TextPanelDebug.Category.TextView);
#endif
_mirror = (lineProperties.FlowDirection == FlowDirection.RightToLeft);
_dcp = dcp;
_showParagraphEllipsis = showParagraphEllipsis;
_wrappingWidth = width;
_line = _owner.TextFormatter.FormatLine(this, dcp, width, lineProperties, textLineBreak, textRunCache);
}
// -----------------------------------------------------------------
// Arrange content of formatted line.
//
// vc - Visual collection of the parent.
// lineOffset - Offset of the line.
// ------------------------------------------------------------------
internal virtual void Arrange(VisualCollection vc, Vector lineOffset)
{
}
// ------------------------------------------------------------------
// Render formatted line.
//
// ctx - Drawing context to be used for rendering.
// lineOffset - Offset of the line.
// wrappingWidth - Wrapping width for the line.
// -----------------------------------------------------------------
internal void Render(DrawingContext ctx, Point lineOffset)
{
Debug.Assert(_line != null, "Rendering line that has not been measured yet.");
// Handle text trimming.
System.Windows.Media.TextFormatting.TextLine line = _line;
if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
{
line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
Debug.Assert(line.HasCollapsed, "Line has not been collapsed");
}
double delta = CalculateXOffsetShift();
line.Draw(ctx, new Point(lineOffset.X + delta, lineOffset.Y), (_mirror ? InvertAxes.Horizontal : InvertAxes.None));
}
// ------------------------------------------------------------------
// Retrieve bounds of an object/character at specified text position.
//
// characterIndex - position of an object/character
// flowDirection - flow direction of object/character
//
// Returns: Bounds of an object/character.
// -----------------------------------------------------------------
internal Rect GetBoundsFromTextPosition(int characterIndex, out FlowDirection flowDirection)
{
return GetBoundsFromPosition(characterIndex, 1, out flowDirection);
}
///
/// Returns an ArrayList of rectangles (Rect) that form the bounds of the region specified between
/// the start and end points
///
///
/// int offset indicating the starting point of the region for which bounds are required
///
/// Length in characters of the region for which bounds are required
///
///
/// Offset of line in x direction, to be added to line bounds to get actual rectangle for line
///
///
/// Offset of line in y direction, to be added to line bounds to get actual rectangle for line
///
///
/// This function calls GetTextBounds for the line, and then checks if there are text run bounds. If they exist,
/// it uses those as the bounding rectangles. If not, it returns the rectangle for the first (and only) element
/// of the text bounds.
///
internal List GetRangeBounds(int cp, int cch, double xOffset, double yOffset)
{
List rectangles = new List();
// Adjust x offset for trailing spaces
double delta = CalculateXOffsetShift();
double adjustedXOffset = xOffset + delta;
IList textBounds;
if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
{
// We should not shift offset in this case
Invariant.Assert(DoubleUtil.AreClose(delta, 0));
System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");
textBounds = line.GetTextBounds(cp, cch);
}
else
{
textBounds = _line.GetTextBounds(cp, cch);
}
Invariant.Assert(textBounds.Count > 0);
for (int boundIndex = 0; boundIndex < textBounds.Count; boundIndex++)
{
Rect rect = textBounds[boundIndex].Rectangle;
rect.X += adjustedXOffset;
rect.Y += yOffset;
rectangles.Add(rect);
}
return rectangles;
}
//-------------------------------------------------------------------
// Retrieve text position index from the distance.
//
// distance - distance relative to the beginning of the line
//
// Returns: Text position index.
//-------------------------------------------------------------------
internal CharacterHit GetTextPositionFromDistance(double distance)
{
// Adjust distance to account for a line shift due to rendering of trailing spaces
double delta = CalculateXOffsetShift();
if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
{
System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
Invariant.Assert(DoubleUtil.AreClose(delta, 0));
Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");
return line.GetCharacterHitFromDistance(distance);
}
return _line.GetCharacterHitFromDistance(distance - delta);
}
//--------------------------------------------------------------------
// Retrieve text position for next caret position
//
// index: CharacterHit for current position
//
// Returns: Text position index.
//-------------------------------------------------------------------
internal CharacterHit GetNextCaretCharacterHit(CharacterHit index)
{
return _line.GetNextCaretCharacterHit(index);
}
//--------------------------------------------------------------------
// Retrieve text position for previous caret position
//
// index: CharacterHit for current position
//
// Returns: Text position index.
//--------------------------------------------------------------------
internal CharacterHit GetPreviousCaretCharacterHit(CharacterHit index)
{
return _line.GetPreviousCaretCharacterHit(index);
}
//-------------------------------------------------------------------
// Retrieve text position for backspace caret position
//
// index: CharacterHit for current position
//
// Returns: Text position index.
//--------------------------------------------------------------------
internal CharacterHit GetBackspaceCaretCharacterHit(CharacterHit index)
{
return _line.GetBackspaceCaretCharacterHit(index);
}
///
/// Returns true of char hit is at caret unit boundary.
///
///
/// CharacterHit to be tested.
///
internal bool IsAtCaretCharacterHit(CharacterHit charHit)
{
return _line.IsAtCaretCharacterHit(charHit, _dcp);
}
// -----------------------------------------------------------------
// Find out if there are any inline objects.
// -----------------------------------------------------------------
internal virtual bool HasInlineObjects()
{
return false;
}
// -----------------------------------------------------------------
// Hit tests to the correct ContentElement within the line.
//
// offset - offset within the line.
//
// Returns: ContentElement which has been hit.
// ------------------------------------------------------------------
internal virtual IInputElement InputHitTest(double offset)
{
return null;
}
///
/// Passes linebreak object back up from contained line
///
internal TextLineBreak GetTextLineBreak()
{
if(_line == null)
{
return null;
}
return _line.GetTextLineBreak();
}
// -----------------------------------------------------------------
// Get length of content hidden by ellipses.
//
// wrappingWidth - Wrapping width for the line.
//
// Returns: Length of collapsed content (number of characters hidden
// by ellipses).
// ------------------------------------------------------------------
internal int GetEllipsesLength()
{
// There are no ellipses, if:
// * there is no overflow in the line
// * text trimming is turned off
if (!_line.HasOverflowed) { return 0; }
if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None) { return 0; }
// Create collapsed text line to get length of collapsed content.
System.Windows.Media.TextFormatting.TextLine collapsedLine = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
Debug.Assert(collapsedLine.HasCollapsed, "Line has not been collapsed");
IList collapsedRanges = collapsedLine.GetTextCollapsedRanges();
if (collapsedRanges != null)
{
Debug.Assert(collapsedRanges.Count == 1, "Multiple collapsed ranges are not supported.");
TextCollapsedRange collapsedRange = collapsedRanges[0];
return collapsedRange.Length;
}
return 0;
}
// ------------------------------------------------------------------
// Gets width of content, collapsed at wrappingWidth (if necessary)
//
// wrappingWidth - Wrapping width for the line.
//
// Returns: Width of content, after collapse (may be greater than wrappingWidth)
//
// -----------------------------------------------------------------
internal double GetCollapsedWidth()
{
// There are no ellipses, if:
// * there is no overflow in the line
// * text trimming is turned off
if (!_line.HasOverflowed)
{
return Width;
}
if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None)
{
return Width;
}
// Create collapsed text line to get length of collapsed content.
System.Windows.Media.TextFormatting.TextLine collapsedLine = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
Debug.Assert(collapsedLine.HasCollapsed, "Line has not been collapsed");
return collapsedLine.Width;
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Internal Properties
//
//-------------------------------------------------------------------
#region Internal Properties
// -----------------------------------------------------------------
// Calculated width of the line.
// -----------------------------------------------------------------
internal double Width
{
get
{
if (IsWidthAdjusted)
{
// Trailing spaces add to width
return _line.WidthIncludingTrailingWhitespace;
}
else
{
return _line.Width;
}
}
}
// ------------------------------------------------------------------
// Distance from the beginning of paragraph edge to the line edge.
// -----------------------------------------------------------------
internal double Start
{
get
{
if (IsXOffsetAdjusted)
{
return _line.Start + CalculateXOffsetShift();
}
else
{
return _line.Start;
}
}
}
// ------------------------------------------------------------------
// Height of the line; line advance distance.
// ------------------------------------------------------------------
internal double Height { get { return _line.Height; } }
// -----------------------------------------------------------------
// Distance from top to baseline of this text line.
// ------------------------------------------------------------------
internal double BaselineOffset { get { return _line.Baseline; } }
// -----------------------------------------------------------------
// Is this the last line of the paragraph?
// -----------------------------------------------------------------
internal bool EndOfParagraph
{
get
{
// If there are no Newline characters, it is not the end of paragraph.
if (_line.NewlineLength == 0) { return false; }
// Since there are Newline characters in the line, do more expensive and
// accurate check.
IList> runs = _line.GetTextRunSpans();
return (((TextSpan)runs[runs.Count-1]).Value is TextEndOfParagraph);
}
}
// -----------------------------------------------------------------
// Length of the line excluding any synthetic characters.
// ------------------------------------------------------------------
internal int Length { get { return _line.Length - (EndOfParagraph ? _syntheticCharacterLength : 0); } }
// -----------------------------------------------------------------
// Length of the line excluding any synthetic characters and line breaks.
// ------------------------------------------------------------------
internal int ContentLength { get { return _line.Length - _line.NewlineLength; } }
#endregion Internal Properties
//--------------------------------------------------------------------
//
// Protected Methods
//
//-------------------------------------------------------------------
#region Protected Methods
// ------------------------------------------------------------------
// Retrieve bounds of an object/character at specified text index.
//
// cp - character index of an object/character
// cch - number of positions occupied by object/character
// flowDirection - flow direction of object/character
//
// Returns: Bounds of an object/character.
// -----------------------------------------------------------------
protected Rect GetBoundsFromPosition(int cp, int cch, out FlowDirection flowDirection)
{
Rect rect;
// Adjust x offset for trailing spaces
double delta = CalculateXOffsetShift();
IList textBounds;
if (_line.HasOverflowed && _owner.ParagraphProperties.TextTrimming != TextTrimming.None)
{
// We should not shift offset in this case
Invariant.Assert(DoubleUtil.AreClose(delta, 0));
System.Windows.Media.TextFormatting.TextLine line = _line.Collapse(GetCollapsingProps(_wrappingWidth, _owner.ParagraphProperties));
Invariant.Assert(line.HasCollapsed, "Line has not been collapsed");
textBounds = line.GetTextBounds(cp, cch);
}
else
{
textBounds = _line.GetTextBounds(cp, cch);
}
Invariant.Assert(textBounds != null && textBounds.Count == 1, "Expecting exactly one TextBounds for a single text position.");
IList runBounds = textBounds[0].TextRunBounds;
if (runBounds != null)
{
Debug.Assert(runBounds.Count == 1, "Expecting exactly one TextRunBounds for a single text position.");
rect = runBounds[0].Rectangle;
}
else
{
rect = textBounds[0].Rectangle;
}
rect.X += delta;
flowDirection = textBounds[0].FlowDirection;
return rect;
}
// -----------------------------------------------------------------
// Get collapsing properties.
//
// wrappingWidth - wrapping width for collapsed line.
// paraProperties - paragraph properties.
//
// Returns: Line collapsing properties.
// -----------------------------------------------------------------
protected TextCollapsingProperties GetCollapsingProps(double wrappingWidth, LineProperties paraProperties)
{
Debug.Assert(paraProperties.TextTrimming != TextTrimming.None, "Text trimming must be enabled.");
TextCollapsingProperties collapsingProps;
if (paraProperties.TextTrimming == TextTrimming.CharacterEllipsis)
{
collapsingProps = new TextTrailingCharacterEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
}
else
{
collapsingProps = new TextTrailingWordEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
}
return collapsingProps;
}
///
/// Returns amount of shift for X-offset to render trailing spaces
///
protected double CalculateXOffsetShift()
{
// Assert that textblock autosize is working correctly and that moving the offset back
// will not result in the front of the line being taken off rendered area
if (IsXOffsetAdjusted)
{
if (_textAlignment == TextAlignment.Center)
{
// Return trailing spaces length divided by two so line remains centered
return (_line.Width - _line.WidthIncludingTrailingWhitespace) / 2;
}
else
{
return (_line.Width - _line.WidthIncludingTrailingWhitespace);
}
}
else
{
return 0.0;
}
}
#endregion Protected Methods
//--------------------------------------------------------------------
//
// Protected Properites
//
//-------------------------------------------------------------------
#region Protected Properties
///
/// True if eliipsis is displayed in the line
///
protected bool ShowEllipsis
{
get
{
if (_owner.ParagraphProperties.TextTrimming == TextTrimming.None)
{
return false;
}
if (_line.HasOverflowed || _showParagraphEllipsis)
{
return true;
}
return false;
}
}
///
/// True if line ends in hard line break
///
protected bool HasLineBreak
{
get
{
return (_line.NewlineLength > 0);
}
}
///
/// True if line's X-offset needs adjustment to render trailing spaces
///
protected bool IsXOffsetAdjusted
{
get
{
return ((_textAlignment == TextAlignment.Right || _textAlignment == TextAlignment.Center) && IsWidthAdjusted);
}
}
///
/// True if line's width is adjusted to include trailing spaces. For right and center alignment we need to
/// adjust line offset as well, but for left alignment we need to only make a width asjustment
///
protected bool IsWidthAdjusted
{
get
{
bool adjusted = false;
// Trailing spaces rendered only around hard breaks
if (HasLineBreak || EndOfParagraph)
{
// Lines with ellipsis are not shifted because ellipsis would not appear after trailing spaces
if (!ShowEllipsis)
{
adjusted = true;
}
}
return adjusted;
}
}
#endregion Protected Properties
//--------------------------------------------------------------------
//
// Private Fields
//
//--------------------------------------------------------------------
#region Private Fields
// -----------------------------------------------------------------
// Owner of the line.
// ------------------------------------------------------------------
protected System.Windows.Controls.TextBlock _owner;
// -----------------------------------------------------------------
// Cached text line.
// -----------------------------------------------------------------
protected System.Windows.Media.TextFormatting.TextLine _line;
// -----------------------------------------------------------------
// Index of the first character in the line.
// ------------------------------------------------------------------
protected int _dcp;
// -----------------------------------------------------------------
// Synthetic character length.
// ------------------------------------------------------------------
protected static int _syntheticCharacterLength = 1;
// ------------------------------------------------------------------
// Is text mirrored?
// -----------------------------------------------------------------
protected bool _mirror;
///
/// Alignment direction of line. Set during formatting.
///
protected TextAlignment _textAlignment;
///
/// Does the line habe paragraph ellipsis. This is determined during formatting depending upon
/// the type of line properties passed.
///
protected bool _showParagraphEllipsis;
///
/// Wrapping width of line
///
protected double _wrappingWidth;
#endregion Private Fields
}
}
// 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
- AppDomainManager.cs
- DiagnosticTraceSource.cs
- EventListenerClientSide.cs
- TableLayoutSettings.cs
- TraceHandler.cs
- IISMapPath.cs
- ValidationResult.cs
- XmlKeywords.cs
- EffectiveValueEntry.cs
- FixedStringLookup.cs
- RefreshPropertiesAttribute.cs
- Enum.cs
- ListMarkerSourceInfo.cs
- ExtensionWindow.cs
- FileDialog.cs
- EntityContainerEmitter.cs
- FastEncoderWindow.cs
- ResourcesBuildProvider.cs
- CornerRadiusConverter.cs
- AncillaryOps.cs
- PageSetupDialog.cs
- Environment.cs
- Utilities.cs
- DataServiceProcessingPipeline.cs
- View.cs
- ExtendedProperty.cs
- LambdaCompiler.Generated.cs
- CodeMethodInvokeExpression.cs
- WizardStepBase.cs
- UnsafeNativeMethods.cs
- StyleXamlTreeBuilder.cs
- StylusPointPropertyUnit.cs
- SafeRegistryHandle.cs
- Scheduler.cs
- PrinterSettings.cs
- DataGridViewRowsRemovedEventArgs.cs
- IncrementalCompileAnalyzer.cs
- KeyedHashAlgorithm.cs
- BuildDependencySet.cs
- Hashtable.cs
- SamlConstants.cs
- DataTableClearEvent.cs
- BitmapDownload.cs
- ZipIOExtraFieldElement.cs
- DependencyStoreSurrogate.cs
- MouseButtonEventArgs.cs
- DataGridBoolColumn.cs
- GeneralTransform3DGroup.cs
- ImageAnimator.cs
- DuplexChannelBinder.cs
- NativeCppClassAttribute.cs
- MailAddressCollection.cs
- JournalEntry.cs
- BindableAttribute.cs
- StringFormat.cs
- WebPartAddingEventArgs.cs
- PartialCachingAttribute.cs
- DataColumnMapping.cs
- ResizeGrip.cs
- PkcsMisc.cs
- BitmapDecoder.cs
- SerialPort.cs
- FontCacheUtil.cs
- ComplexObject.cs
- JulianCalendar.cs
- HtmlCommandAdapter.cs
- ScrollChangedEventArgs.cs
- SQLInt32Storage.cs
- Deflater.cs
- WebContentFormatHelper.cs
- Array.cs
- CodeAssignStatement.cs
- AssemblyLoader.cs
- ChtmlTextWriter.cs
- QuadraticBezierSegment.cs
- MessagePartProtectionMode.cs
- ApplicationHost.cs
- FontSource.cs
- ParameterBinding.cs
- FormClosingEvent.cs
- IgnoreDataMemberAttribute.cs
- AutomationPeer.cs
- CopyOnWriteList.cs
- TableLayoutStyle.cs
- CommonServiceBehaviorElement.cs
- TraceHandler.cs
- Propagator.ExtentPlaceholderCreator.cs
- XmlSchemaSubstitutionGroup.cs
- sqlnorm.cs
- MultiDataTrigger.cs
- XmlSchemaExternal.cs
- ASCIIEncoding.cs
- BitmapImage.cs
- _RegBlobWebProxyDataBuilder.cs
- ReliabilityContractAttribute.cs
- StyleSelector.cs
- ToolStripDropDownButton.cs
- RenderTargetBitmap.cs
- TextEditorThreadLocalStore.cs
- ImageCodecInfo.cs