[FriendAccessAllowed] // used by Framework static internal TextFormatter CreateFromContext(TextFormatterContext soleContext, TextFormattingMode textFormattingMode) #endif { // create a new instance of TextFormatter for the specified context. // This creation prohibits the use of multiple contexts within the same TextFormatter via reentrance. return(new TextFormatterImp(soleContext, textFormattingMode)); }
private IntPtr CreatePTSContext(int index, TextFormattingMode textFormattingMode) { PtsHost ptsHost = this._contextPool[index].PtsHost; Invariant.Assert(ptsHost != null); IntPtr installedObjects; int installedObjectsCount; this.InitInstalledObjectsInfo(ptsHost, ref this._contextPool[index].SubtrackParaInfo, ref this._contextPool[index].SubpageParaInfo, out installedObjects, out installedObjectsCount); this._contextPool[index].InstalledObjects = installedObjects; this.InitGenericInfo(ptsHost, (IntPtr)(index + 1), installedObjects, installedObjectsCount, ref this._contextPool[index].ContextInfo); this.InitFloaterObjInfo(ptsHost, ref this._contextPool[index].FloaterInit); this.InitTableObjInfo(ptsHost, ref this._contextPool[index].TableobjInit); if (this._contextPool[index].IsOptimalParagraphEnabled) { TextFormatterContext textFormatterContext = new TextFormatterContext(); TextPenaltyModule textPenaltyModule = textFormatterContext.GetTextPenaltyModule(); IntPtr ptsPenaltyModule = textPenaltyModule.DangerousGetHandle(); this._contextPool[index].TextPenaltyModule = textPenaltyModule; this._contextPool[index].ContextInfo.ptsPenaltyModule = ptsPenaltyModule; this._contextPool[index].TextFormatter = TextFormatter.CreateFromContext(textFormatterContext, textFormattingMode); GC.SuppressFinalize(this._contextPool[index].TextPenaltyModule); } IntPtr result; PTS.Validate(PTS.CreateDocContext(ref this._contextPool[index].ContextInfo, out result)); return(result); }
[FriendAccessAllowed] // used by Framework static internal TextFormatter CreateFromContext(TextFormatterContext soleContext) #endif { // create a new instance of TextFormatter for the specified context. // This creation prohibits the use of multiple contexts within the same TextFormatter via reentrance. return new TextFormatterImp(soleContext, TextFormattingMode.Ideal); }
/// <summary> /// Client to acquire a state at the point where line is broken by line breaking process; /// can be null when the line ends by the ending of the paragraph. Client may pass this /// value back to TextFormatter as an input argument to TextFormatter.FormatLine when /// formatting the next line within the same paragraph. /// </summary> /// <remarks> /// TextLineBreak is a finalizable object which may contain a reference to an unmanaged /// structure called break record. Break record can be acquired thru ploline. This method /// acquire break record only when the passing ploline object is not NULL. /// /// Not all situations requires break record. Single-line formatting without complex text /// object does not need it, but optimal break session does. For performance reason, we /// should not produce break record unnecessarily because it makes TextLineBreak become /// finalizable, which therefore unnecessarily put additional pressure to GC since each /// finalizable object wakes finalizer thread and requires double GC collections. /// </remarks> internal TextLineBreak GetTextLineBreak(IntPtr ploline) { IntPtr pbreakrec = IntPtr.Zero; if (ploline != IntPtr.Zero) { LsErr lserr = UnsafeNativeMethods.LoAcquireBreakRecord(ploline, out pbreakrec); if (lserr != LsErr.None) { TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.AcquireBreakRecordFailure, lserr), lserr); } } if (_lastRun != null && _lastRun.TextModifierScope != null && !(_lastRun.TextRun is TextEndOfParagraph)) { return(new TextLineBreak( _lastRun.TextModifierScope, new SecurityCriticalDataForSet <IntPtr>(pbreakrec) )); } return((pbreakrec != IntPtr.Zero) ? new TextLineBreak(null, new SecurityCriticalDataForSet <IntPtr>(pbreakrec)) : null); }
[FriendAccessAllowed] // used by Framework static internal TextFormatter CreateFromContext(TextFormatterContext soleContext, TextFormattingMode textFormattingMode) #endif { // create a new instance of TextFormatter for the specified context. // This creation prohibits the use of multiple contexts within the same TextFormatter via reentrance. if (!use_managed && !presentationnative_works) { try { MS.Internal.TextFormatting.TextStore.IsSpace(' '); } catch (TypeInitializationException e) { use_managed = true; } if (!use_managed) { presentationnative_works = true; } } if (use_managed) { return(new Managed.TextFormatting.TextFormatterImp(textFormattingMode)); } else { return(new MS.Internal.TextFormatting.TextFormatterImp(soleContext, textFormattingMode)); } }
/// <summary> /// Construct an instance of TextFormatter implementation with the specified context /// </summary> /// <param name="soleContext"></param> /// <remarks> /// 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. /// </remarks> internal TextFormatterImp(TextFormatterContext soleContext, TextFormattingMode textFormattingMode) { _textFormattingMode = textFormattingMode; if (soleContext != null) _contextList.Add(soleContext); _multipleContextProhibited = (_contextList.Count != 0); }
private bool _penalizedAsJustified; // flag indicating whether the paragraph should be penalized as fully-justified one /// <summary> /// Construct a paragraph cache to be used during optimal paragraph formatting /// </summary> internal TextParagraphCache( FormatSettings settings, int firstCharIndex, int paragraphWidth ) { Invariant.Assert(settings != null); // create full text _finiteFormatWidth = settings.GetFiniteFormatWidth(paragraphWidth); _fullText = FullTextState.Create(settings, firstCharIndex, _finiteFormatWidth); // acquiring LS context TextFormatterContext context = settings.Formatter.AcquireContext(_fullText, IntPtr.Zero); _fullText.SetTabs(context); IntPtr ploparabreakValue = IntPtr.Zero; LsErr lserr = context.CreateParaBreakingSession( firstCharIndex, _finiteFormatWidth, // breakrec is not needed before the first cp of para cache // since we handle Bidi break ourselves. IntPtr.Zero, ref ploparabreakValue, ref _penalizedAsJustified ); // get the exception in context before it is released Exception callbackException = context.CallbackException; // release the context context.Release(); if (lserr != LsErr.None) { GC.SuppressFinalize(this); if (callbackException != null) { // rethrow exception thrown in callbacks throw new InvalidOperationException(SR.Get(SRID.CreateParaBreakingSessionFailure, lserr), callbackException); } else { // throw with LS error codes TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.CreateParaBreakingSessionFailure, lserr), lserr); } } _ploparabreak.Value = ploparabreakValue; // keep context alive till here GC.KeepAlive(context); }
/// <summary> /// Construct an instance of TextFormatter implementation with the specified context /// </summary> /// <param name="soleContext"></param> /// <remarks> /// 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. /// </remarks> internal TextFormatterImp(TextFormatterContext soleContext, TextFormattingMode textFormattingMode) { _textFormattingMode = textFormattingMode; if (soleContext != null) { _contextList.Add(soleContext); } _multipleContextProhibited = (_contextList.Count != 0); }
internal TextPenaltyModule(SecurityCriticalDataForSet <IntPtr> ploc) { IntPtr ploPenaltyModule; LsErr lserr = UnsafeNativeMethods.LoAcquirePenaltyModule(ploc.Value, out ploPenaltyModule); if (lserr != LsErr.None) { TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.AcquirePenaltyModuleFailure, lserr), lserr); } _ploPenaltyModule.Value = ploPenaltyModule; }
/// <summary> /// Set tab stops /// </summary> internal void SetTabs(TextFormatterContext context) { unsafe { ParaProp pap = _store.Pap; FormatSettings settings = _store.Settings; // set up appropriate tab stops int incrementalTab = TextFormatterImp.RealToIdeal(pap.DefaultIncrementalTab); int lsTbdCount = pap.Tabs != null ? pap.Tabs.Count : 0; LsTbd[] lsTbds; if (_markerStore != null) { if (pap.Tabs != null && pap.Tabs.Count > 0) { lsTbdCount = pap.Tabs.Count + 1; lsTbds = new LsTbd[lsTbdCount]; lsTbds[0].ur = settings.TextIndent; // marker requires a tab stop at text start position fixed(LsTbd *plsTbds = &lsTbds[1]) { CreateLsTbds(pap, plsTbds, lsTbdCount - 1); context.SetTabs(incrementalTab, plsTbds - 1, lsTbdCount); } } else { LsTbd markerRequiredLsTbd = new LsTbd(); markerRequiredLsTbd.ur = settings.TextIndent; // marker requires a tab stop at text start position context.SetTabs(incrementalTab, &markerRequiredLsTbd, 1); } } else { if (pap.Tabs != null && pap.Tabs.Count > 0) { lsTbds = new LsTbd[lsTbdCount]; fixed(LsTbd *plsTbds = &lsTbds[0]) { CreateLsTbds(pap, plsTbds, lsTbdCount); context.SetTabs(incrementalTab, plsTbds, lsTbdCount); } } else { // work with only incremental tab context.SetTabs(incrementalTab, null, 0); } } } }
public TextLineBreak Clone() { IntPtr pbreakrec = IntPtr.Zero; if (_breakRecord.Value != IntPtr.Zero) { LsErr lserr = UnsafeNativeMethods.LoCloneBreakRecord(_breakRecord.Value, out pbreakrec); if (lserr != LsErr.None) { TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.CloneBreakRecordFailure, lserr), lserr); } } return(new TextLineBreak(_currentScope, new SecurityCriticalDataForSet <IntPtr>(pbreakrec))); }
internal override SecurityCriticalDataForSet <IntPtr> GetTextPenaltyResource() { if (_isDisposed) { throw new ObjectDisposedException(SR.Get(SRID.TextBreakpointHasBeenDisposed)); } LsErr lserr = UnsafeNativeMethods.LoRelievePenaltyResource(_ploline.Value); if (lserr != LsErr.None) { TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.RelievePenaltyResourceFailure, lserr), lserr); } return(_penaltyResource); }
internal IntPtr DangerousGetHandle() { if (_isDisposed) { throw new ObjectDisposedException(SR.Get(SRID.TextPenaltyModuleHasBeenDisposed)); } IntPtr penaltyModuleInternalHandle; LsErr lserr = UnsafeNativeMethods.LoGetPenaltyModuleInternalHandle(_ploPenaltyModule.Value, out penaltyModuleInternalHandle); if (lserr != LsErr.None) { TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.GetPenaltyModuleHandleFailure, lserr), lserr); } GC.KeepAlive(this); return(penaltyModuleInternalHandle); }
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; }
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); }
/// <summary> /// Client to create a new instance of TextFormatter from the specified TextFormatter context /// </summary> /// <param name="soleContext">TextFormatter context</param> /// <returns>New instance of TextFormatter</returns> #if OPTIMALBREAK_API static public TextFormatter CreateFromContext(TextFormatterContext soleContext)
internal void SetTabs(TextFormatterContext context) { unsafe { ParaProp pap = _store.Pap; FormatSettings settings = _store.Settings; // set up appropriate tab stops int incrementalTab = TextFormatterImp.RealToIdeal(pap.DefaultIncrementalTab); int lsTbdCount = pap.Tabs != null ? pap.Tabs.Count : 0; LsTbd[] lsTbds; if (_markerStore != null) { if (pap.Tabs != null && pap.Tabs.Count > 0) { lsTbdCount = pap.Tabs.Count + 1; lsTbds = new LsTbd[lsTbdCount]; lsTbds[0].ur = settings.TextIndent; // marker requires a tab stop at text start position fixed (LsTbd* plsTbds = &lsTbds[1]) { CreateLsTbds(pap, plsTbds, lsTbdCount - 1); context.SetTabs(incrementalTab, plsTbds - 1, lsTbdCount); } } else { LsTbd markerRequiredLsTbd = new LsTbd(); markerRequiredLsTbd.ur = settings.TextIndent; // marker requires a tab stop at text start position context.SetTabs(incrementalTab, &markerRequiredLsTbd, 1); } } else { if (pap.Tabs != null && pap.Tabs.Count > 0) { lsTbds = new LsTbd[lsTbdCount]; fixed (LsTbd* plsTbds = &lsTbds[0]) { CreateLsTbds(pap, plsTbds, lsTbdCount); context.SetTabs(incrementalTab, plsTbds, lsTbdCount); } } else { // work with only incremental tab context.SetTabs(incrementalTab, null, 0); } } } }
internal sealed override unsafe void GetAdvanceWidthsUnshaped( char *characterString, int characterLength, double scalingFactor, int *advanceWidthsUnshaped ) { if (!IsShapingRequired) { if ((_shapeTypeface != null) && (_shapeTypeface.DeviceFont != null)) { // Use device font to compute advance widths _shapeTypeface.DeviceFont.GetAdvanceWidths( characterString, characterLength, _emSize * scalingFactor, advanceWidthsUnshaped ); } else { bool nullFont; GlyphTypeface glyphTypeface = GetGlyphTypeface(out nullFont); Invariant.Assert(glyphTypeface != null); glyphTypeface.GetAdvanceWidthsUnshaped( characterString, characterLength, _emSize, (float)_properties.PixelsPerDip, scalingFactor, advanceWidthsUnshaped, nullFont, _textFormattingMode, _isSideways ); } } else { GlyphTypeface glyphTypeface = _shapeTypeface.GlyphTypeface; Invariant.Assert(glyphTypeface != null); Invariant.Assert(characterLength > 0); CharacterBufferRange newBuffer = new CharacterBufferRange(characterString, characterLength); MS.Internal.Text.TextInterface.GlyphMetrics[] glyphMetrics = BufferCache.GetGlyphMetrics(characterLength); glyphTypeface.GetGlyphMetricsOptimized(newBuffer, _emSize, (float)_properties.PixelsPerDip, _textFormattingMode, _isSideways, glyphMetrics ); if (_textFormattingMode == TextFormattingMode.Display && TextFormatterContext.IsSpecialCharacter(*characterString)) { // (DDVSO 92892) If the run starts with a special character (in // the LineServices sense), we apply display-mode rounding now, // as we won't get another chance. This assumes that the characters // in a run are either all special or all non-special; that assumption // is valid in the current LS implementation. double designToEm = _emSize / glyphTypeface.DesignEmHeight; double pixelsPerDip = _properties.PixelsPerDip; for (int i = 0; i < characterLength; i++) { advanceWidthsUnshaped[i] = (int)Math.Round(TextFormatterImp.RoundDipForDisplayMode(glyphMetrics[i].AdvanceWidth * designToEm, pixelsPerDip) * scalingFactor); } } else { // For the normal case, rounding is applied later on when LS // invokes the callback GetGlyphPositions, so that adjustments // due to justification and shaping are taken into account. double designToEm = _emSize * scalingFactor / glyphTypeface.DesignEmHeight; for (int i = 0; i < characterLength; i++) { advanceWidthsUnshaped[i] = (int)Math.Round(glyphMetrics[i].AdvanceWidth * designToEm); } } BufferCache.ReleaseGlyphMetrics(glyphMetrics); } }
/// <summary> /// Client to create a new instance of TextFormatter from the specified TextFormatter context /// </summary> /// <param name="soleContext">TextFormatter context</param> /// <returns>New instance of TextFormatter</returns> #if OPTIMALBREAK_API static public TextFormatter CreateFromContext(TextFormatterContext soleContext, TextFormattingMode textFormattingMode)
private IntPtr CreatePTSContext(int index, TextFormattingMode textFormattingMode) { PtsHost ptsHost; IntPtr installedObjects; int installedObjectsCount; TextFormatterContext textFormatterContext; IntPtr context; ptsHost = _contextPool[index].PtsHost; Invariant.Assert(ptsHost != null); // Create installed object info. InitInstalledObjectsInfo(ptsHost, ref _contextPool[index].SubtrackParaInfo, ref _contextPool[index].SubpageParaInfo, out installedObjects, out installedObjectsCount); _contextPool[index].InstalledObjects = installedObjects; // Create generic callbacks info. InitGenericInfo(ptsHost, (IntPtr)(index + 1), installedObjects, installedObjectsCount, ref _contextPool[index].ContextInfo); // Preallocated floater and table info. InitFloaterObjInfo(ptsHost, ref _contextPool[index].FloaterInit); InitTableObjInfo(ptsHost, ref _contextPool[index].TableobjInit); // Setup for optimal paragraph if (_contextPool[index].IsOptimalParagraphEnabled) { textFormatterContext = new TextFormatterContext(); TextPenaltyModule penaltyModule = textFormatterContext.GetTextPenaltyModule(); IntPtr ptsPenaltyModule = penaltyModule.DangerousGetHandle(); _contextPool[index].TextPenaltyModule = penaltyModule; _contextPool[index].ContextInfo.ptsPenaltyModule = ptsPenaltyModule; _contextPool[index].TextFormatter = TextFormatter.CreateFromContext(textFormatterContext, textFormattingMode); // Explicitly take the penalty module object out of finalization queue; // PTSCache must manage lifetime of the penalty module explicitly by calling // TextPenaltyModule.Dispose to ensure proper destruction order of PTSContext // and the penalty module (PTS context must be destroyed first). GC.SuppressFinalize(_contextPool[index].TextPenaltyModule); } // Create PTS Context PTS.Validate(PTS.CreateDocContext(ref _contextPool[index].ContextInfo, out context)); return context; }
internal static IList <TextBreakpoint> CreateMultiple( TextParagraphCache paragraphCache, int firstCharIndex, int maxLineWidth, TextLineBreak previousLineBreak, IntPtr penaltyRestriction, out int bestFitIndex ) { Invariant.Assert(paragraphCache != null); // grab full text state from paragraph cache FullTextState fullText = paragraphCache.FullText; Invariant.Assert(fullText != null); FormatSettings settings = fullText.TextStore.Settings; Invariant.Assert(settings != null); // update formatting parameters at line start settings.UpdateSettingsForCurrentLine( maxLineWidth, previousLineBreak, (firstCharIndex == fullText.TextStore.CpFirst) ); Invariant.Assert(settings.Formatter != null); // acquiring LS context TextFormatterContext context = settings.Formatter.AcquireContext(fullText, IntPtr.Zero); IntPtr previousBreakRecord = IntPtr.Zero; if (settings.PreviousLineBreak != null) { previousBreakRecord = settings.PreviousLineBreak.BreakRecord.Value; } // need not consider marker as tab since marker does not affect line metrics and it wasnt drawn. fullText.SetTabs(context); LsBreaks lsbreaks = new LsBreaks(); LsErr lserr = context.CreateBreaks( fullText.GetBreakpointInternalCp(firstCharIndex), previousBreakRecord, paragraphCache.Ploparabreak.Value, // para breaking session penaltyRestriction, ref lsbreaks, out bestFitIndex ); // get the exception in context before it is released Exception callbackException = context.CallbackException; // release the context context.Release(); if (lserr != LsErr.None) { if (callbackException != null) { // rethrow exception thrown in callbacks throw callbackException; } else { // throw with LS error codes TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.CreateBreaksFailure, lserr), lserr); } } // keep context alive at least till here GC.KeepAlive(context); TextBreakpoint[] breakpoints = new TextBreakpoint[lsbreaks.cBreaks]; for (int i = 0; i < lsbreaks.cBreaks; i++) { breakpoints[i] = new FullTextBreakpoint( fullText, firstCharIndex, maxLineWidth, ref lsbreaks, i // the current break ); } return(breakpoints); }
private IntPtr CreatePTSContext(int index, TextFormattingMode textFormattingMode) { PtsHost ptsHost; IntPtr installedObjects; int installedObjectsCount; TextFormatterContext textFormatterContext; IntPtr context; ptsHost = _contextPool[index].PtsHost; Invariant.Assert(ptsHost != null); InitInstalledObjectsInfo(ptsHost, ref _contextPool[index].SubtrackParaInfo, ref _contextPool[index].SubpageParaInfo, out installedObjects, out installedObjectsCount); _contextPool[index].InstalledObjects = installedObjects; InitGenericInfo(ptsHost, (IntPtr)(index + 1), installedObjects, installedObjectsCount, ref _contextPool[index].ContextInfo); InitFloaterObjInfo(ptsHost, ref _contextPool[index].FloaterInit); InitTableObjInfo(ptsHost, ref _contextPool[index].TableobjInit); if (_contextPool[index].IsOptimalParagraphEnabled) { textFormatterContext = new TextFormatterContext(); TextPenaltyModule penaltyModule = textFormatterContext.GetTextPenaltyModule(); IntPtr ptsPenaltyModule = penaltyModule.DangerousGetHandle(); _contextPool[index].TextPenaltyModule = penaltyModule; _contextPool[index].ContextInfo.ptsPenaltyModule = ptsPenaltyModule; _contextPool[index].TextFormatter = TextFormatter.CreateFromContext(textFormatterContext, textFormattingMode); GC.SuppressFinalize(_contextPool[index].TextPenaltyModule); } PTS.Validate(PTS.CreateDocContext(ref _contextPool[index].ContextInfo, out context)); return context; }