Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / MS / Internal / TextFormatting / TextFormatterImp.cs / 2 / TextFormatterImp.cs
//+------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation // // File: TextFormatterImp.cs // // Contents: Text formatter implementation // // Created: 2-25-2003 [....] ([....]) // //----------------------------------------------------------------------- using System; using System.Security; using System.Windows; using System.Windows.Media; using System.Windows.Threading; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Media.TextFormatting; using MS.Utility; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; using MS.Internal.Shaping; #if !OPTIMALBREAK_API using MS.Internal.PresentationCore; #endif namespace MS.Internal.TextFormatting { ////// Implementation of TextFormatter /// internal sealed class TextFormatterImp : TextFormatter { private FrugalStructList_contextList; // LS context free list private double _toIdeal; // scaling factor from client's real space to LS ideal resolution private double _toReal; // scaling factor from LS ideal resolution to client's real space private bool _multipleContextProhibited; // prohibit multiple contexts within the same formatter private GlyphingCache _glyphingCache; // Glyphing cache for font linking process private const int MaxGlyphingCacheCapacity = 16; /// /// Construct an instance of TextFormatter implementation /// internal TextFormatterImp() : this(null) {} ////// Construct an instance of TextFormatter implementation with the specified context /// /// ////// TextFormatter created via this special ctor takes a specified context and uses it as the only known /// context within its entire lifetime. It prohibits reentering of TextFormatter during formatting as only /// one context is allowed. This restriction is critical to the optimal break algorithm supported by the current /// version of PTLS. /// internal TextFormatterImp(TextFormatterContext soleContext) { _toIdeal = Constants.DefaultRealToIdeal; _toReal = Constants.DefaultIdealToReal; if (soleContext != null) _contextList.Add(soleContext); _multipleContextProhibited = (_contextList.Count != 0); } ////// Finalizing text formatter /// ~TextFormatterImp() { CleanupInternal(); } ////// Release all unmanaged LS contexts /// public override void Dispose() { CleanupInternal(); base.Dispose(); GC.SuppressFinalize(this); } ////// Release all unmanaged LS contexts /// private void CleanupInternal() { for (int i = 0; i < _contextList.Count; i++) { _contextList[i].Destroy(); } _contextList.Clear(); } ////// Client to format a text line that fills a paragraph in the document. /// /// an object representing text layout clients text source for TextFormatter. /// character index to specify where in the source text the line starts /// width of paragraph in which the line fills /// properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation. /// LineBreak property of the previous text line, or null if this is the first line in the paragraph ///object representing a line of text that client interacts with. public override TextLine FormatLine( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak ) { return FormatLineInternal( textSource, firstCharIndex, 0, // lineLength paragraphWidth, paragraphProperties, previousLineBreak, new TextRunCache() // local cache, only live within this call ); } ////// Client to format a text line that fills a paragraph in the document. /// /// an object representing text layout clients text source for TextFormatter. /// character index to specify where in the source text the line starts /// width of paragraph in which the line fills /// properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation. /// LineBreak property of the previous text line, or null if this is the first line in the paragraph /// an object representing content cache of the client. ///object representing a line of text that client interacts with. public override TextLine FormatLine( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { return FormatLineInternal( textSource, firstCharIndex, 0, // lineLength paragraphWidth, paragraphProperties, previousLineBreak, textRunCache ); } ////// Client to reconstruct a previously formatted text line /// /// an object representing text layout clients text source for TextFormatter. /// character index to specify where in the source text the line starts /// character length of the line /// width of paragraph in which the line fills /// properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation. /// LineBreak property of the previous text line, or null if this is the first line in the paragraph /// an object representing content cache of the client. ///object representing a line of text that client interacts with. #if OPTIMALBREAK_API public override TextLine RecreateLine( #else internal override TextLine RecreateLine( #endif TextSource textSource, int firstCharIndex, int lineLength, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { return FormatLineInternal( textSource, firstCharIndex, lineLength, paragraphWidth, paragraphProperties, previousLineBreak, textRunCache ); } ////// Format and produce a text line either with or without previously known /// line break point. /// private TextLine FormatLineInternal( TextSource textSource, int firstCharIndex, int lineLength, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), EventType.StartEvent, "TextFormatterImp.FormatLineInternal Start" ); } // prepare formatting settings FormatSettings settings = PrepareFormatSettings( textSource, firstCharIndex, paragraphWidth, paragraphProperties, previousLineBreak, textRunCache, (lineLength != 0), // Do optimal break if break is given true // isSingleLineFormatting ); TextLine textLine = null; if ( !settings.Pap.AlwaysCollapsible && previousLineBreak == null && lineLength <= 0 ) { // simple text line. textLine = SimpleTextLine.Create( settings, firstCharIndex, RealToIdealFloor(paragraphWidth) ) as TextLine; } if (textLine == null) { // content is complex, creating complex line textLine = new TextMetrics.FullTextLine( settings, firstCharIndex, lineLength, RealToIdealFloor(paragraphWidth), LineFlags.None ) as TextLine; } if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), EventType.EndEvent, "TextFormatterImp.FormatLineInternal End" ); } return textLine; } ////// Client to ask for the possible smallest and largest paragraph width that can fully contain the passing text content /// /// an object representing text layout clients text source for TextFormatter. /// character index to specify where in the source text the line starts /// properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation. ///min max paragraph width public override MinMaxParagraphWidth FormatMinMaxParagraphWidth( TextSource textSource, int firstCharIndex, TextParagraphProperties paragraphProperties ) { return FormatMinMaxParagraphWidth( textSource, firstCharIndex, paragraphProperties, new TextRunCache() // local cache, only live within this call ); } ////// Client to ask for the possible smallest and largest paragraph width that can fully contain the passing text content /// /// an object representing text layout clients text source for TextFormatter. /// character index to specify where in the source text the line starts /// properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation. /// an object representing content cache of the client. ///min max paragraph width public override MinMaxParagraphWidth FormatMinMaxParagraphWidth( TextSource textSource, int firstCharIndex, TextParagraphProperties paragraphProperties, TextRunCache textRunCache ) { // prepare formatting settings FormatSettings settings = PrepareFormatSettings( textSource, firstCharIndex, 0, // infinite paragraphWidth paragraphProperties, null, // always format the whole paragraph - no previousLineBreak textRunCache, false, // optimalBreak true // isSingleLineFormatting ); // create specialized line specifically for min/max calculation TextMetrics.FullTextLine line = new TextMetrics.FullTextLine( settings, firstCharIndex, 0, // lineLength 0, // paragraph width has no significant meaning in min/max calculation (LineFlags.KeepState | LineFlags.MinMax) ); // line width in this case is the width of a line when the entire paragraph is laid out // as a single long line. MinMaxParagraphWidth minMax = new MinMaxParagraphWidth(line.MinWidth, line.Width); line.Dispose(); return minMax; } ////// Client to cache information about a paragraph to be used during optimal paragraph line formatting /// /// an object representing text layout clients text source for TextFormatter. /// character index to specify where in the source text the line starts /// width of paragraph in which the line fills /// properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation. /// text formatting state at the point where the previous line in the paragraph /// was broken by the text formatting process, as specified by the TextLine.LineBreak property for the previous /// line; this parameter can be null, and will always be null for the first line in a paragraph. /// an object representing content cache of the client. ///object representing a line of text that client interacts with. #if OPTIMALBREAK_API public override TextParagraphCache CreateParagraphCache( #else internal override TextParagraphCache CreateParagraphCache( #endif TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { // prepare formatting settings FormatSettings settings = PrepareFormatSettings( textSource, firstCharIndex, paragraphWidth, paragraphProperties, previousLineBreak, textRunCache, true, // optimalBreak false // !isSingleLineFormatting ); // // Optimal paragraph formatting session specific check // if (!settings.Pap.Wrap && settings.Pap.OptimalBreak) { // Optimal paragraph must wrap. throw new ArgumentException(SR.Get(SRID.OptimalParagraphMustWrap)); } // create paragraph content cache object return new TextParagraphCache( settings, firstCharIndex, RealToIdeal(paragraphWidth) ); } ////// Validate all the relevant text formatting initial settings and package them /// private FormatSettings PrepareFormatSettings( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache, bool useOptimalBreak, bool isSingleLineFormatting ) { VerifyTextFormattingArguments( textSource, firstCharIndex, paragraphWidth, paragraphProperties, textRunCache ); if (textRunCache.Imp == null) { // No run cache object available, create one textRunCache.Imp = new TextRunCacheImp(); } // initialize formatting settings return new FormatSettings( this, textSource, textRunCache.Imp, new ParaProp(this, paragraphProperties, useOptimalBreak), previousLineBreak, isSingleLineFormatting ); } ////// Verify all text formatting arguments /// private void VerifyTextFormattingArguments( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextRunCache textRunCache ) { if (textSource == null) throw new ArgumentNullException("textSource"); if (textRunCache == null) throw new ArgumentNullException("textRunCache"); if (paragraphProperties == null) throw new ArgumentNullException("paragraphProperties"); if (paragraphProperties.DefaultTextRunProperties == null) throw new ArgumentNullException("paragraphProperties.DefaultTextRunProperties"); if (paragraphProperties.DefaultTextRunProperties.Typeface == null) throw new ArgumentNullException("paragraphProperties.DefaultTextRunProperties.Typeface"); if (DoubleUtil.IsNaN(paragraphWidth)) throw new ArgumentOutOfRangeException("paragraphWidth", SR.Get(SRID.ParameterValueCannotBeNaN)); if (double.IsInfinity(paragraphWidth)) throw new ArgumentOutOfRangeException("paragraphWidth", SR.Get(SRID.ParameterValueCannotBeInfinity)); double realInfiniteWidth = IdealToReal(Constants.InfiniteWidth); if ( paragraphWidth < 0 || paragraphWidth > realInfiniteWidth) { throw new ArgumentOutOfRangeException("paragraphWidth", SR.Get(SRID.ParameterMustBeBetween, 0, realInfiniteWidth)); } double realMaxFontRenderingEmSize = realInfiniteWidth / Constants.GreatestMutiplierOfEm; if ( paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize < 0 || paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize > realMaxFontRenderingEmSize) { throw new ArgumentOutOfRangeException("paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize", SR.Get(SRID.ParameterMustBeBetween, 0, realMaxFontRenderingEmSize)); } if (paragraphProperties.Indent > realInfiniteWidth) throw new ArgumentOutOfRangeException("paragraphProperties.Indent", SR.Get(SRID.ParameterCannotBeGreaterThan, realInfiniteWidth)); if (paragraphProperties.LineHeight > realInfiniteWidth) throw new ArgumentOutOfRangeException("paragraphProperties.LineHeight", SR.Get(SRID.ParameterCannotBeGreaterThan, realInfiniteWidth)); if ( paragraphProperties.DefaultIncrementalTab < 0 || paragraphProperties.DefaultIncrementalTab > realInfiniteWidth) { throw new ArgumentOutOfRangeException("paragraphProperties.DefaultIncrementalTab", SR.Get(SRID.ParameterMustBeBetween, 0, realInfiniteWidth)); } } ////// Validate the input character hit /// internal static void VerifyCaretCharacterHit( CharacterHit characterHit, int cpFirst, int cchLength ) { if ( characterHit.FirstCharacterIndex < cpFirst || characterHit.FirstCharacterIndex > cpFirst + cchLength) { throw new ArgumentOutOfRangeException("First", SR.Get(SRID.ParameterMustBeBetween, cpFirst, cpFirst + cchLength)); } if (characterHit.TrailingLength < 0) { throw new ArgumentOutOfRangeException("Length", SR.Get(SRID.ParameterCannotBeNegative)); } } ////// Acquire a free TextFormatter context for complex line operation /// /// object that becomes the owner of LS context once acquired /// matching PLOC ///Active LS context ////// Critical - this sets the owner of the context /// Safe - this doesn't expose critical info /// [SecurityCritical, SecurityTreatAsSafe] internal TextFormatterContext AcquireContext( object owner, IntPtr ploc ) { Invariant.Assert(owner != null); TextFormatterContext context = null; int c; int contextCount = _contextList.Count; for (c = 0; c < contextCount; c++) { context = (TextFormatterContext)_contextList[c]; if (ploc == IntPtr.Zero) { if(context.Owner == null) break; } else if (ploc == context.Ploc.Value) { // LS requires that we use the exact same context for line // destruction or hittesting (part of the reason is that LS // actually caches some run info in the context). So here // we use the actual PLSC as the context signature so we // locate the one we want. Debug.Assert(context.Owner == null); break; } } if (c == contextCount) { if (contextCount == 0 || !_multipleContextProhibited) { // no free one exists, create a new one context = new TextFormatterContext(); _contextList.Add(context); } else { // This instance of TextFormatter only allows a single context, reentering the // same TextFormatter in this case is not allowed. // // This requirement is currently enforced only during optimal break computation. // Client implementing nesting of optimal break content inside another must create // a separate TextFormatter instance for each content in different nesting level. throw new InvalidOperationException(SR.Get(SRID.TextFormatterReentranceProhibited)); } } Debug.Assert(context != null); context.Owner = owner; return context; } ////// Create an anti-inversion transform from the inversion flags. /// The result is used to correct glyph bitmap on an output to /// a drawing surface with the specified inversions applied on. /// internal static MatrixTransform CreateAntiInversionTransform( InvertAxes inversion, double paragraphWidth, double lineHeight ) { if (inversion == InvertAxes.None) { // avoid creating unncessary pressure on GC when anti-transform is not needed. return null; } double m11 = 1; double m22 = 1; double offsetX = 0; double offsetY = 0; if ((inversion & InvertAxes.Horizontal) != 0) { m11 = -m11; offsetX = paragraphWidth; } if ((inversion & InvertAxes.Vertical) != 0) { m22 = -m22; offsetY = lineHeight; } return new MatrixTransform(m11, 0, 0, m22, offsetX, offsetY); } ////// Scale LS ideal resolution value to real value /// internal double IdealToReal(int i) { return i * _toReal; } ////// Scale real value to LS ideal resolution /// internal int RealToIdeal(double i) { return (int) Math.Round(i * _toIdeal); } ////// Scale the real value to LS ideal resolution /// Use the floor value of the scale value /// ////// Using Math.Round may result in a line larger than /// the actual given paragraph width. For example, /// round tripping 100.112 with factor 300 becomes 100.1133... /// Using floor to ensure we never go beyond paragraph width /// internal int RealToIdealFloor(double i) { return (int) Math.Floor(i * _toIdeal); } ////// Ideal to real value scaling factor /// internal double ToReal { get { return _toReal; } } ////// Real to ideal value scaling factor /// internal double ToIdeal { get { return _toIdeal; } } ////// Return the GlyphingCache associated with this TextFormatterImp object. /// GlyphingCache stores the mapping from Unicode scalar value to the physical font that is /// used to display it. /// internal GlyphingCache GlyphingCache { get { if (_glyphingCache == null) { _glyphingCache = new GlyphingCache(MaxGlyphingCacheCapacity); } return _glyphingCache; } } } } // 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
- ScrollChrome.cs
- xmlfixedPageInfo.cs
- PathGeometry.cs
- GeneralTransform3DTo2D.cs
- SymLanguageVendor.cs
- UnsafeNativeMethodsMilCoreApi.cs
- PageContent.cs
- BuildResultCache.cs
- WeakReference.cs
- WindowsGraphics.cs
- GifBitmapDecoder.cs
- PolicyValidationException.cs
- RenderingEventArgs.cs
- ObjectItemAssemblyLoader.cs
- ImportDesigner.xaml.cs
- WebServiceReceiveDesigner.cs
- TranslateTransform3D.cs
- GenericUriParser.cs
- InstancePersistenceEvent.cs
- HotCommands.cs
- XmlSchemaImport.cs
- Classification.cs
- XmlObjectSerializerWriteContext.cs
- AssemblyGen.cs
- ComNativeDescriptor.cs
- Validator.cs
- PeerHelpers.cs
- ContextMenuStrip.cs
- EditorZoneBase.cs
- StringUtil.cs
- NumberEdit.cs
- ScriptingScriptResourceHandlerSection.cs
- ListViewHitTestInfo.cs
- XsdBuilder.cs
- DeviceContext.cs
- CheckBox.cs
- SystemPens.cs
- FixedSOMLineRanges.cs
- HttpResponse.cs
- ImageMetadata.cs
- StatusBar.cs
- SchemaTableColumn.cs
- XamlFxTrace.cs
- baseaxisquery.cs
- OleDbRowUpdatingEvent.cs
- BitmapEffectGroup.cs
- SoapExtensionReflector.cs
- FontStretches.cs
- GridViewUpdatedEventArgs.cs
- StringWriter.cs
- HMACSHA1.cs
- DataFieldEditor.cs
- TextRunCacheImp.cs
- DbException.cs
- StaticResourceExtension.cs
- BooleanFacetDescriptionElement.cs
- DropShadowBitmapEffect.cs
- ToolboxItemImageConverter.cs
- VirtualDirectoryMapping.cs
- DataGridViewRowPostPaintEventArgs.cs
- Matrix.cs
- InlinedAggregationOperatorEnumerator.cs
- WindowHelperService.cs
- CustomLineCap.cs
- AjaxFrameworkAssemblyAttribute.cs
- SourceInterpreter.cs
- UriTemplateDispatchFormatter.cs
- HostedTransportConfigurationBase.cs
- TablePattern.cs
- entityreference_tresulttype.cs
- StrokeRenderer.cs
- ToolStripTextBox.cs
- ConfigXmlElement.cs
- IsolatedStorageFile.cs
- UserControl.cs
- BitmapDecoder.cs
- SemaphoreSlim.cs
- LicenseManager.cs
- PageParser.cs
- FilterFactory.cs
- MetadataItemSerializer.cs
- InvalidFilterCriteriaException.cs
- DbProviderConfigurationHandler.cs
- SqlUdtInfo.cs
- TypeSemantics.cs
- DocumentViewerAutomationPeer.cs
- XmlNullResolver.cs
- FatalException.cs
- CharEnumerator.cs
- SiteMapNodeItemEventArgs.cs
- ZipPackage.cs
- ActiveXHost.cs
- DriveNotFoundException.cs
- NoClickablePointException.cs
- ExeContext.cs
- ZipIOExtraField.cs
- CustomPopupPlacement.cs
- Domain.cs
- Atom10FormatterFactory.cs
- GradientStopCollection.cs