예제 #1
0
        /// <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);
        }
예제 #2
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);
        }
예제 #3
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;
        }
예제 #4
0
        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);
        }
예제 #5
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)));
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }