Beispiel #1
0
 /// <summary>
 /// Construct an lsrun
 /// </summary>
 private LSRun(
     TextRunInfo runInfo,
     IList <TextEffect> textEffects,
     Plsrun type,
     int offsetToFirstCp,
     int textRunLength,
     int emSize,
     ushort charFlags,
     CharacterBufferRange charBufferRange,
     int baselineOffset,
     int height,
     TextShapeableSymbols shapeable,
     byte bidiLevel
     )
 {
     _runInfo         = runInfo;
     _type            = type;
     _offsetToFirstCp = offsetToFirstCp;
     _textRunLength   = textRunLength;
     _emSize          = emSize;
     _charFlags       = charFlags;
     _charBufferRange = charBufferRange;
     _baselineOffset  = baselineOffset;
     _height          = height;
     _bidiLevel       = bidiLevel;
     _shapeable       = shapeable;
     _textEffects     = textEffects;
 }
Beispiel #2
0
        private IList <TextEffect> _textEffects;                    // TextEffects that should be applied for this run


        /// <summary>
        /// Construct an lsrun
        /// </summary>
        internal LSRun(
            TextRunInfo runInfo,
            IList <TextEffect> textEffects,
            Plsrun type,
            int offsetToFirstCp,
            int textRunLength,
            int emSize,
            ushort charFlags,
            CharacterBufferRange charBufferRange,
            TextShapeableSymbols shapeable,
            double realToIdeal,
            byte bidiLevel
            ) :
            this(
                runInfo,
                textEffects,
                type,
                offsetToFirstCp,
                textRunLength,
                emSize,
                charFlags,
                charBufferRange,
                (shapeable != null ? (int)Math.Round(shapeable.Baseline * realToIdeal) : 0),
                (shapeable != null ? (int)Math.Round(shapeable.Height * realToIdeal) : 0),
                shapeable,
                bidiLevel
                )
        {
        }
Beispiel #3
0
        /// <summary>
        /// Constructing a textrun info
        /// </summary>
        /// <param name="charBufferRange">characte buffer range for the run</param>
        /// <param name="textRunLength">textrun length</param>
        /// <param name="offsetToFirstCp">character offset to run first cp</param>
        /// <param name="textRun">text run</param>
        /// <param name="lsRunType">the internal LS run type </param>
        /// <param name="charFlags">character attribute flags</param>
        /// <param name="digitCulture">digit culture for the run</param>
        /// <param name="contextualSubstitution">contextual number substitution for the run</param>
        /// <param name="symbolTypeface">if true, indicates a text run in a symbol (i.e., non-Unicode) font</param>
        /// <param name="modifierScope">The current TextModifier scope for this TextRunInfo</param>
        internal TextRunInfo(
            CharacterBufferRange charBufferRange,
            int textRunLength,
            int offsetToFirstCp,
            TextRun textRun,
            Plsrun lsRunType,
            ushort charFlags,
            CultureInfo digitCulture,
            bool contextualSubstitution,
            bool symbolTypeface,
            TextModifierScope modifierScope
            )
        {
            _charBufferRange = charBufferRange;
            _textRunLength   = textRunLength;
            _offsetToFirstCp = offsetToFirstCp;
            _textRun         = textRun;
            _plsrun          = lsRunType;
            _charFlags       = charFlags;
            _digitCulture    = digitCulture;
            _runFlags        = 0;
            _modifierScope   = modifierScope;

            if (contextualSubstitution)
            {
                _runFlags |= (ushort)RunFlags.ContextualSubstitution;
            }

            if (symbolTypeface)
            {
                _runFlags |= (ushort)RunFlags.IsSymbol;
            }
        }
Beispiel #4
0
        private IList<TextEffect>       _textEffects;               // TextEffects that should be applied for this run
 

        /// <summary>
        /// Construct an lsrun
        /// </summary> 
        internal LSRun(
            TextRunInfo             runInfo, 
            IList<TextEffect>       textEffects, 
            Plsrun                  type,
            int                     offsetToFirstCp, 
            int                     textRunLength,
            int                     emSize,
            ushort                  charFlags,
            CharacterBufferRange    charBufferRange, 
            TextShapeableSymbols    shapeable,
            double                  realToIdeal, 
            byte                    bidiLevel 
            ) :
            this( 
                runInfo,
                textEffects,
                type,
                offsetToFirstCp, 
                textRunLength,
                emSize, 
                charFlags, 
                charBufferRange,
                (shapeable != null ? (int)Math.Round(shapeable.Baseline * realToIdeal) : 0), 
                (shapeable != null ? (int)Math.Round(shapeable.Height * realToIdeal) : 0),
                shapeable,
                bidiLevel
                ) 
        {}
Beispiel #5
0
        /// <summary>
        /// Map LSCP to host CP, and return the last LSRun
        /// before the specified limit.
        /// </summary>
        internal LSRun CountText(
            int lscpLim,
            int cpFirst,
            out int count
            )
        {
            LSRun lastRun = null;

            count = 0;

            int lsccp = lscpLim - _store.CpFirst;

            Debug.Assert(lsccp > 0, "Zero-length text line!");

            foreach (Span span in _store.PlsrunVector)
            {
                if (lsccp <= 0)
                {
                    break;
                }

                Plsrun plsrun = (Plsrun)span.element;

                // There should be no marker runs in _plsrunVector.
                Debug.Assert(!TextStore.IsMarker(plsrun));

                // Is it a normal, non-static, LSRun?
                if (plsrun >= Plsrun.FormatAnchor)
                {
                    // Get the run and remember the last run.
                    lastRun = _store.GetRun(plsrun);

                    // Accumulate the length.
                    int cpRun = lastRun.Length;
                    if (cpRun > 0)
                    {
                        if (lsccp < span.length && cpRun == span.length)
                        {
                            count += lsccp;
                            break;
                        }
                        count += cpRun;
                    }
                }

                lsccp -= span.length;
            }

            // make char count relative to cpFirst as the cpFirst of this metrics may not
            // be the same as the cpFirst of the store in optimal paragraph formatting.
            count = count - cpFirst + _store.CpFirst;

            return(lastRun);
        }
Beispiel #6
0
 /// <summary>
 /// Construct an lsrun for a constant control char
 /// </summary>
 internal LSRun(
     Plsrun type,
     IntPtr controlChar
     ) :
     this(
         null,   // text run info
         type,
         controlChar,
         0,      // textRunLength
         -1,     // offsetToFirstChar
         0
         )
 {
 }
Beispiel #7
0
        /// <summary>
        /// Convert the specified external CP to LSCP corresponding to a possible break position for optimal break.
        /// </summary>
        /// <remarks>
        /// There is a generic issue that one CP could map to multiple LSCPs when it comes to
        /// lsrun that occupies no actual CP. Such lsrun is generated by line layout during
        /// formatting to accomplsih specific purpose i.e. run representing open and close
        /// reverse object or a fake-linebreak lsrun.
        ///
        /// According to SergeyGe and Antons, LS will never breaks immediately after open reverse
        /// or immediately before close reverse. It also never break before a linebreak character.
        ///
        /// Therefore, it is safe to make an assumption here that one CP will indeed map to one
        /// LSCP given being the LSCP before the open reverse and the LSCP after the close reverse.
        /// Never the vice-versa.
        ///
        /// This is the reason why the loop inside this method may overread the PLSRUN span by
        /// one span at the end. The loop is designed to skip over all the lsruns with zero CP
        /// which is not the open reverse.
        ///
        /// This logic is exactly the same as the one used by FullTextLine.PrefetchLSRuns. Any
        /// attempt to change it needs to be thoroughly reviewed. The same logic is to be applied
        /// accordingly on PrefetchLSRuns.
        ///
        /// [Wchao, 5-24-2005]
        ///
        /// </remarks>
        internal int GetBreakpointInternalCp(int cp)
        {
            int ccp        = cp - _store.CpFirst;
            int lscp       = _store.CpFirst;
            int ccpCurrent = 0;

            SpanVector plsrunVector = _store.PlsrunVector;
            LSRun      lsrun;
            int        i = 0;

            int lastSpanLength = 0;
            int lastRunLength  = 0;

            do
            {
                Span   span   = plsrunVector[i];
                Plsrun plsrun = (Plsrun)span.element;
                lsrun = _store.GetRun(plsrun);

                if (ccp == ccpCurrent && lsrun.Type == Plsrun.Reverse)
                {
                    break;
                }

                lastSpanLength = span.length;
                lastRunLength  = (plsrun >= Plsrun.FormatAnchor ? lsrun.Length : 0);

                lscp       += lastSpanLength;
                ccpCurrent += lastRunLength;
            } while (++i < plsrunVector.Count &&
                     lsrun.Type != Plsrun.ParaBreak &&
                     ccp >= ccpCurrent
                     );

            // Since we may overread the span vector by one span,
            // we need to subtract the accumulated lscp by the number of cp we may have overread.

            if (ccpCurrent == ccp || lastSpanLength == lastRunLength)
            {
                return(lscp - ccpCurrent + ccp);
            }

            Invariant.Assert(ccpCurrent - ccp == lastRunLength);
            return(lscp - lastSpanLength);
        }
Beispiel #8
0
 internal LSRun(
     TextRunInfo runInfo,
     Plsrun type,
     IntPtr controlChar,
     int textRunLength,
     int offsetToFirstCp,
     byte bidiLevel
     )
 {
     unsafe
     {
         _runInfo         = runInfo;
         _type            = type;
         _charBufferRange = new CharacterBufferRange((char *)controlChar, 1);
         _textRunLength   = textRunLength;
         _offsetToFirstCp = offsetToFirstCp;
         _bidiLevel       = bidiLevel;
     }
 }
Beispiel #9
0
 /// <summary>
 /// Construct an lsrun for a constant control char 
 /// </summary> 
 internal LSRun(
     Plsrun      type, 
     IntPtr      controlChar
     ) :
     this(
         null,   // text run info 
         type,
         controlChar, 
         0,      // textRunLength 
         -1,     // offsetToFirstChar
         0 
         )
 {}
        internal LsErr GetRunStrikethroughInfo(
            IntPtr          pols,           // Line Layout context
            Plsrun          plsrun,         // plsrun
            ref LsHeights   lsHeights,      // run height
            LsTFlow         textFlow,       // text flow direction
            ref LsStInfo    stInfo          // [out] result strikethrough info
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                lsrun = Draw.CurrentLine.GetRun(plsrun);

                Debug.Assert(
                    !TextStore.IsContent(plsrun) || lsrun.Type == Plsrun.Text || lsrun.Type == Plsrun.InlineObject,
                    "Invalid run"
                    );

                stInfo = new LsStInfo();

                double strikeThroughPositionInEm;
                double strikeThroughThicknessInEm;

                GetLSRunStrikethroughMetrics(lsrun, out strikeThroughPositionInEm, out strikeThroughThicknessInEm);

                stInfo.cNumberOfLines = 1;
                stInfo.dvpLowerStrikethroughOffset = (int)Math.Round(lsrun.EmSize * strikeThroughPositionInEm);
                stInfo.dvpLowerStrikethroughSize = (int)Math.Round(lsrun.EmSize * strikeThroughThicknessInEm);

                Debug.Assert(stInfo.dvpLowerStrikethroughSize >= 0);





                if (stInfo.dvpLowerStrikethroughSize <= 0)
                    stInfo.dvpLowerStrikethroughSize = 1;
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("GetRunStrikethroughInfo", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal LsErr GetRunUnderlineInfo(
            IntPtr          pols,           // Line Layout context
            Plsrun          plsrun,         // plsrun
            ref LsHeights   lsHeights,      // run height
            LsTFlow         textFlow,       // text flow direction
            ref LsULInfo    ulInfo          // [out] result underline info
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                lsrun = Draw.CurrentLine.GetRun(plsrun);

                Debug.Assert(
                    !TextStore.IsContent(plsrun) || lsrun.Type == Plsrun.Text || lsrun.Type == Plsrun.InlineObject,
                    "Invalid run"
                    );

                ulInfo = new LsULInfo();

                double underlinePositionInEm;
                double underlineThicknessInEm;

                if (lsrun.Shapeable != null)
                {
                    underlinePositionInEm = lsrun.Shapeable.UnderlinePosition;
                    underlineThicknessInEm = lsrun.Shapeable.UnderlineThickness;
                }
                else
                {

                    underlinePositionInEm = lsrun.RunProp.Typeface.UnderlinePosition;
                    underlineThicknessInEm = lsrun.RunProp.Typeface.UnderlineThickness;
                }

                ulInfo.cNumberOfLines = 1;
                ulInfo.dvpFirstUnderlineOffset = (int)Math.Round(lsrun.EmSize * -underlinePositionInEm);
                ulInfo.dvpFirstUnderlineSize = (int)Math.Round(lsrun.EmSize * underlineThicknessInEm);






                Debug.Assert(ulInfo.dvpFirstUnderlineSize >= 0);

                if (ulInfo.dvpFirstUnderlineSize <= 0)
                    ulInfo.dvpFirstUnderlineSize = 1;
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("GetAutoNumberInfo", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal LsErr GetDurMaxExpandRagged(
            IntPtr      pols,               // Line Layout context
            Plsrun      plsrun,             // plsrun
            LsTFlow     lstFlow,            // text flow
            ref int     maxExpandRagged     // [out] em width
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {



                lsrun = FullText.StoreFrom(plsrun).GetRun(plsrun);
                maxExpandRagged = lsrun.EmSize;
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("GetDurMaxExpandRagged", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal unsafe LsErr GetRunCharWidths(
            IntPtr          pols,               // Line Layout context
            Plsrun          plsrun,             // plsrun
            LsDevice        device,             // kind of device
            char*           charString,         // character string
            int             stringLength,       // string length
            int             maxWidth,           // max width allowance
            LsTFlow         textFlow,           // text flow
            int*            charWidths,         // [out] returning char widths up to given upperbound
            ref int         totalWidth,         // [out] total run width
            ref int         stringLengthFitted  // [out] number of char fitted
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                TextFormatterImp formatter;

                if (FullText != null)
                {
                    lsrun = FullText.StoreFrom(plsrun).GetRun(plsrun);
                    formatter = FullText.Formatter;
                }
                else
                {








                    #if DEBUG



                    Debug.Assert(Draw.CurrentLine.FullTextState != null);
                    #endif
                    lsrun = Draw.CurrentLine.GetRun(plsrun);
                    formatter = Draw.CurrentLine.Formatter;
                }

                if (lsrun.Type == Plsrun.Text)
                {
                    Debug.Assert(lsrun.Shapeable != null && stringLength > 0);
                    lsrun.Shapeable.GetAdvanceWidthsUnshaped(charString, stringLength, TextFormatterImp.ToIdeal, charWidths);

                    totalWidth = 0;
                    stringLengthFitted = 0;

                    do
                    {
                        totalWidth += charWidths[stringLengthFitted];

                    } while (
                            ++stringLengthFitted < stringLength
                        && totalWidth <= maxWidth
                        );

                    if (totalWidth <= maxWidth && FullText != null)
                    {
                        int cpLimit = lsrun.OffsetToFirstCp + stringLengthFitted;
                        if (cpLimit > FullText.CpMeasured)
                        {
                            FullText.CpMeasured = cpLimit;
                        }
                    }
                }
                else
                {

                    charWidths[0] = 0;
                    totalWidth = 0;
                    stringLengthFitted = stringLength;
                }
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("GetRunCharWidths", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal LsErr GetRunTextMetrics(
            System.IntPtr       pols,           // Line Layout context
            Plsrun              plsrun,         // plsrun
            LsDevice            lsDevice,       // kind of device
            LsTFlow             lstFlow,        // text flow
            ref LsTxM           lstTextMetrics  // [out] returning metrics
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                FullTextState fullText = FullText;
                TextStore store = fullText.StoreFrom(plsrun);
                lsrun = store.GetRun(plsrun);

                if (lsrun.Height > 0)
                {
                    lstTextMetrics.dvAscent = lsrun.BaselineOffset;
                    lstTextMetrics.dvMultiLineHeight = lsrun.Height;
                }
                else
                {
                    Typeface typeface = store.Pap.DefaultTypeface;
                    lstTextMetrics.dvAscent = (int)Math.Round(typeface.Baseline(store.Pap.EmSize, Constants.DefaultIdealToReal, Util.PixelsPerDip, fullText.TextFormattingMode));
                    lstTextMetrics.dvMultiLineHeight = (int)Math.Round(typeface.LineSpacing(store.Pap.EmSize, Constants.DefaultIdealToReal, Util.PixelsPerDip, fullText.TextFormattingMode));
                }

                lstTextMetrics.dvDescent = lstTextMetrics.dvMultiLineHeight - lstTextMetrics.dvAscent;
                lstTextMetrics.fMonospaced = 0;
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("GetRunTextMetrics", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal LsErr FInterruptShaping(
            IntPtr          pols,               // Line Layout context
            LsTFlow         textFlow,           // text flow
            Plsrun          plsrunFirst,        // first run
            Plsrun          plsrunSecond,       // second run
            ref int         fIsInterruptOk      // [out] disconnect glyphs between runs?
            )
        {
            LsErr lserr = LsErr.None;

            try
            {
                TextStore store = FullText.StoreFrom(plsrunFirst);

                if (    !TextStore.IsContent(plsrunFirst)
                    ||  !TextStore.IsContent(plsrunSecond))
                {
                    fIsInterruptOk = 1;
                    return LsErr.None;
                }


                LSRun lsrunFirst = store.GetRun(plsrunFirst);
                LSRun lsrunSecond = store.GetRun(plsrunSecond);


                fIsInterruptOk = !(

                    lsrunFirst.BidiLevel == lsrunSecond.BidiLevel

                    && lsrunFirst.Shapeable != null
                    && lsrunSecond.Shapeable != null
                    && lsrunFirst.Shapeable.CanShapeTogether(lsrunSecond.Shapeable)
                    ) ? 1 : 0;

            }
            catch (Exception e)
            {
                SaveException(e, Plsrun.Undefined, null);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("FInterruptShaping", Plsrun.Undefined, null);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
Beispiel #16
0
 /// <summary>
 /// Get a text store containing the specified plsrun
 /// </summary>
 internal TextStore StoreFrom(Plsrun plsrun)
 {
     return(TextStore.IsMarker(plsrun) ? _markerStore : _store);
 }
        internal LsErr DrawStrikethrough(
            IntPtr          pols,           // Line Layout context
            Plsrun          plsrun,         // plsrun
            uint            stType,         // kind of strike
            ref LSPOINT     ptOrigin,       // [in] drawing origin
            int             stLength,       // strike length
            int             stThickness,    // strike thickness
            LsTFlow         textFlow,       // text flow direction
            uint            displayMode,    // display mode
            ref LSRECT      clipRect        // [in] clipping rectangle
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;
            try
            {
                if (!TextStore.IsContent(plsrun))
                {

                    return LsErr.None;
                }

                TextMetrics.FullTextLine currentLine = Draw.CurrentLine;
                lsrun = currentLine.GetRun(plsrun);

                double strikeThroughPositionInEm;
                double strikeThroughThicknessInEm;

                GetLSRunStrikethroughMetrics(lsrun, out strikeThroughPositionInEm, out strikeThroughThicknessInEm);

                int baselineTop = ptOrigin.y + (int)Math.Round(lsrun.EmSize * strikeThroughPositionInEm);
                int overlineTop = baselineTop - (lsrun.BaselineOffset - (int)Math.Round(lsrun.EmSize * strikeThroughThicknessInEm));

                const uint locationMask = 
                    (1U << (int)TextDecorationLocation.OverLine) |
                    (1U << (int)TextDecorationLocation.Strikethrough) |
                    (1U << (int)TextDecorationLocation.Baseline);

                DrawTextDecorations(
                    lsrun,
                    locationMask,
                    ptOrigin.x,   // left
                    0,            // underline top; not used
                    overlineTop,
                    ptOrigin.y,   // strikethrough top from LS
                    baselineTop,
                    stLength,
                    stThickness,
                    textFlow
                    );
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("DrawStrikethrough", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal LsErr DrawUnderline(
            IntPtr pols,                // Line Layout context
            Plsrun      plsrun,         // plsrun
            uint        ulType,         // kind of underline
            ref LSPOINT ptOrigin,       // [in] drawing origin
            int         ulLength,       // underline length
            int         ulThickness,    // underline thickness
            LsTFlow     textFlow,       // text flow direction
            uint        displayMode,    // display mode
            ref LSRECT  clipRect        // [in] clipping rectangle
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;
            try
            {
                if (!TextStore.IsContent(plsrun))
                {

                    return LsErr.None;
                }

                lsrun = Draw.CurrentLine.GetRun(plsrun);

                const uint locationMask = (1U << (int)TextDecorationLocation.Underline);

                DrawTextDecorations(
                    lsrun,
                    locationMask,
                    ptOrigin.x,   // left
                    ptOrigin.y,   // underline top from LS
                    0,            // overline top; not used
                    0,            // strikethrough top; not used
                    0,            // baseline top; not used
                    ulLength,
                    ulThickness,
                    textFlow
                    );
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("DrawUnderline", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
Beispiel #19
0
 /// <summary>
 /// Construct an lsrun 
 /// </summary>
 private LSRun(
     TextRunInfo             runInfo,
     IList<TextEffect>       textEffects, 
     Plsrun                  type,
     int                     offsetToFirstCp, 
     int                     textRunLength, 
     int                     emSize,
     ushort                  charFlags, 
     CharacterBufferRange    charBufferRange,
     int                     baselineOffset,
     int                     height,
     TextShapeableSymbols    shapeable, 
     byte                    bidiLevel
     ) 
 { 
     _runInfo = runInfo;
     _type = type; 
     _offsetToFirstCp = offsetToFirstCp;
     _textRunLength = textRunLength;
     _emSize = emSize;
     _charFlags = charFlags; 
     _charBufferRange = charBufferRange;
     _baselineOffset = baselineOffset; 
     _height = height; 
     _bidiLevel = bidiLevel;
     _shapeable = shapeable; 
     _textEffects = textEffects;
 }
        internal LsErr InlineDraw(
            System.IntPtr   pols,           // Line Layout context
            Plsrun          plsrun,         // plsrun
            ref LSPOINT     ptRun,          // [in] pen position at which to render the object
            LsTFlow         textFlow,       // text flow direction
            int             runWidth        // object width
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                TextMetrics.FullTextLine currentLine = Draw.CurrentLine;
                lsrun = currentLine.GetRun(plsrun);

                LSPOINT lsrunOrigin = ptRun;

                Debug.Assert(lsrun.Type == Plsrun.InlineObject);

                int baseDirection = currentLine.RightToLeft ? 1 : 0;
                int runDirection = (int)(lsrun.BidiLevel & 1);

                if (baseDirection != 0)
                {
                    lsrunOrigin.x = -lsrunOrigin.x;
                }

                TextEmbeddedObject textObject = lsrun.TextRun as TextEmbeddedObject;

                Debug.Assert(textObject != null);
                Debug.Assert(textFlow != LsTFlow.lstflowWS || runDirection != 0);

                if ((baseDirection ^ runDirection) != 0)
                {

                    lsrunOrigin.x -= runWidth;
                }


                Point baselineOrigin = new Point(
                    currentLine.Formatter.IdealToReal(currentLine.LSLineUToParagraphU(lsrunOrigin.x))+ Draw.VectorToLineOrigin.X,
                    currentLine.Formatter.IdealToReal((lsrunOrigin.y + lsrun.BaselineMoveOffset)) + Draw.VectorToLineOrigin.Y
                    );


                Rect objectBounds = textObject.ComputeBoundingBox(
                     baseDirection != 0, // rightToLeft
                    false  // no sideway support yet
                    );

                if (!objectBounds.IsEmpty)
                {


                    objectBounds.X += baselineOrigin.X;
                    objectBounds.Y += baselineOrigin.Y;
                }


                _boundingBox.Union(
                    new Rect(

                    LSRun.UVToXY(
                            Draw.LineOrigin,
                            new Point(),
                            objectBounds.Location.X,
                            objectBounds.Location.Y,
                            currentLine
                            ),

                    LSRun.UVToXY(
                            Draw.LineOrigin,
                            new Point(),
                            objectBounds.Location.X + objectBounds.Size.Width,
                            objectBounds.Location.Y + objectBounds.Size.Height,
                            currentLine
                            )
                        )
                    );

                DrawingContext drawingContext = Draw.DrawingContext;                
                
                if (drawingContext != null)
                {

                    Draw.SetGuidelineY(baselineOrigin.Y);

                    try 
                    {                    
                        if (Draw.AntiInversion == null)
                        {

                            textObject.Draw(
                                drawingContext,
                                LSRun.UVToXY(
                                    Draw.LineOrigin,
                                    new Point(),
                                    baselineOrigin.X,
                                    baselineOrigin.Y,
                                    currentLine
                                    ),
                                baseDirection != 0,
                                false
                                );
                        }
                        else
                        {




                            drawingContext.PushTransform(Draw.AntiInversion);
                            try 
                            {
                                textObject.Draw(drawingContext, baselineOrigin, baseDirection != 0, false);
                            } 
                            finally
                            {
                                drawingContext.Pop();
                            }
                        }
                    }
                    finally 
                    {
                        Draw.UnsetGuidelineY();
                    }
                }
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("InlineDraw", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal LsErr InlineFormat(
            System.IntPtr           pols,               // Line Layout context
            Plsrun                  plsrun,             // plsrun
            int                     lscpInline,         // first cp of the run
            int                     currentPosition,    // inline's current pen location in text direction
            int                     rightMargin,        // right margin
            ref ObjDim              pobjDim,            // [out] object dimension
            out int                 fFirstRealOnLine,   // [out] is this run the first in line
            out int                 fPenPositionUsed,   // [out] is pen position used to format object
            out LsBrkCond           breakBefore,        // [out] break condition before this object
            out LsBrkCond           breakAfter          // [out] break condition after this object
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            fFirstRealOnLine = 0;
            fPenPositionUsed = 0;
            breakBefore = LsBrkCond.Please;
            breakAfter = LsBrkCond.Please;

            try
            {
                TextFormatterImp formatter = FullText.Formatter;

                TextStore store = FullText.StoreFrom(plsrun);
                lsrun = store.GetRun(plsrun);
                TextEmbeddedObject textObject = lsrun.TextRun as TextEmbeddedObject;

                Debug.Assert(textObject != null);

                int cpInline = store.GetExternalCp(lscpInline);

                fFirstRealOnLine = (cpInline == store.CpFirst) ? 1 : 0;

                TextEmbeddedObjectMetrics metrics = store.FormatTextObject(
                    textObject,
                    cpInline,
                    currentPosition,
                    rightMargin
                    );

                pobjDim = new ObjDim();
                pobjDim.dur = TextFormatterImp.RealToIdeal(metrics.Width);
                pobjDim.heightsRef.dvMultiLineHeight = TextFormatterImp.RealToIdeal(metrics.Height);
                pobjDim.heightsRef.dvAscent = TextFormatterImp.RealToIdeal(metrics.Baseline);
                pobjDim.heightsRef.dvDescent = pobjDim.heightsRef.dvMultiLineHeight - pobjDim.heightsRef.dvAscent;
                pobjDim.heightsPres = pobjDim.heightsRef;

                breakBefore = BreakConditionToLsBrkCond(textObject.BreakBefore);
                breakAfter = BreakConditionToLsBrkCond(textObject.BreakAfter);
                fPenPositionUsed = (!textObject.HasFixedSize) ? 1 : 0;


                lsrun.BaselineOffset = pobjDim.heightsRef.dvAscent;
                lsrun.Height = pobjDim.heightsRef.dvMultiLineHeight;
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("InlineFormat", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        internal unsafe LsErr DrawGlyphs(
            IntPtr                      pols,                       // Line Layout context
            Plsrun                      plsrun,                     // plsrun
            char*                       pwchText,                   // character string
            ushort*                     puClusterMap,               // character-to-cluster map
            ushort*                     puCharProperties,           // character properties
            int                         charCount,                  // character count
            ushort*                     puGlyphs,                   // glyph indices
            int*                        piJustifiedGlyphAdvances,   // justified glyph advances
            int*                        piGlyphAdvances,            // original ideal glyph advances
            GlyphOffset*                piiGlyphOffsets,            // glyph offsets
            uint*                       piGlyphProperties,          // glyph properties
            LsExpType*                  plsExpType,                 // glyph expansion types
            int                         glyphCount,                 // glyph count
            LsTFlow                     textFlow,                   // text flow
            uint                        displayMode,                // draw transparent or opaque
            ref LSPOINT                 ptRun,                      // [in] display position (at baseline)
            ref LsHeights               lsHeights,                  // [in] run height metrics
            int                         runWidth,                   // run overall advance width
            ref LSRECT                  clippingRect                // [in] clipping rectangle if any applied
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                TextMetrics.FullTextLine currentLine = Draw.CurrentLine;
                lsrun = currentLine.GetRun(plsrun);

                Debug.Assert(TextStore.IsContent(plsrun) && lsrun.Shapeable != null);

                GlyphRun glyphRun = ComputeShapedGlyphRun(
                    lsrun,
                    currentLine.Formatter,
                    true,           // origin of the glyph run provided at drawing time
                    ptRun,
                    charCount,
                    pwchText,
                    puClusterMap,
                    glyphCount,
                    puGlyphs,
                    piJustifiedGlyphAdvances,
                    piiGlyphOffsets,
                    currentLine.IsJustified
                    );

                if (glyphRun != null)
                {
                    DrawingContext drawingContext = Draw.DrawingContext;

                    Draw.SetGuidelineY(glyphRun.BaselineOrigin.Y);

                    try 
                    {
                        _boundingBox.Union(
                            lsrun.DrawGlyphRun(
                                drawingContext, 
                                null,     // draw with the run's foreground
                                glyphRun
                                )
                            );
                    }
                    finally 
                    {
                        Draw.UnsetGuidelineY();
                    }

                }
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("DrawGlyphs", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
Beispiel #23
0
 internal LSRun(
     TextRunInfo             runInfo,
     Plsrun                  type,
     IntPtr                  controlChar, 
     int                     textRunLength,
     int                     offsetToFirstCp, 
     byte                    bidiLevel 
     )
 { 
     unsafe
     {
         _runInfo = runInfo;
         _type = type; 
         _charBufferRange = new CharacterBufferRange((char*)controlChar, 1);
         _textRunLength = textRunLength; 
         _offsetToFirstCp = offsetToFirstCp; 
         _bidiLevel = bidiLevel;
     } 
 }
        internal unsafe LsErr EnumText(        
            IntPtr                      pols,                           // ls context
            Plsrun                      plsrun,                         // plsrun
            int                         cpFirst,                        // first cp of the ls dnode
            int                         dcp,                            // dcp of the dnode
            char                        *pwchText,                      // characters for glyph run
            int                         cchText,                        // length of characters 
            LsTFlow                     lstFlow,                        // flow direction
            int                         fReverseOrder,                  // flag for reverse order enumeration
            int                         fGeometryProvided,              // flag for providing geometry 
            ref LSPOINT                 pptStart,                       // [in] logical start of the run
            ref LsHeights               pheights,                       // [in] height (iff geometryProvided)
            int                         dupRun,                         // width of the run
            int                         glyphBaseRun,                   // flag for glyph based run
            int                         *piCharAdvances,                // character advance widths (iff !glyphBaseRun)
            ushort                      *puClusterMap,                  // cluster map (iff glyphBaseRun)
            ushort                      *characterProperties,           // character properties (iff glyphBaseRun)
            ushort                      *puGlyphs,                      // glyph indices (iff glyphBaseRun)
            int                         *piJustifiedGlyphAdvances,      // glyph advances (iff glyphBaseRun)
            GlyphOffset                 *piiGlyphOffsets,               // glyph offsets (iff glyphBaseRun)
            uint                        *piGlyphProperties,             // glyph properties (iff glyphProperties)
            int                         glyphCount                      // glyph count
            )
        {
            Debug.Assert(fGeometryProvided == 0, "Line enumeration doesn't need geometry information");

            if (cpFirst < 0)
            {

                return LsErr.None;
            }
            
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try                 
            {   
                TextMetrics.FullTextLine currentLine = Draw.CurrentLine;
                lsrun = currentLine.GetRun(plsrun);
                GlyphRun glyphRun = null;
                if (glyphBaseRun != 0)
                {

                    if (glyphCount > 0)
                    {

                        glyphRun = ComputeShapedGlyphRun(
                            lsrun, 
                            currentLine.Formatter,
                            false,      // glyph run origin not provided
                            pptStart, 
                            cchText, 
                            pwchText, 
                            puClusterMap, 
                            glyphCount, 
                            puGlyphs,
                            piJustifiedGlyphAdvances, 
                            piiGlyphOffsets,
                            currentLine.IsJustified
                            );
                    }
                }
                else if (cchText > 0)
                {

                    dupRun = 0;
                    for (int i = 0; i < cchText; i++)
                    {
                        dupRun += piCharAdvances[i];
                    }

                    

                    glyphRun = ComputeUnshapedGlyphRun(
                        lsrun, 
                        lstFlow, 
                        currentLine.Formatter,
                        false,      // glyph run origin not provided at enumeration
                        pptStart, 
                        dupRun, 
                        cchText, 
                        pwchText, 
                        piCharAdvances,
                        currentLine.IsJustified
                        );
                }
                
                if (glyphRun != null)
                {





                    IndexedGlyphRuns.Add(
                        new IndexedGlyphRun(
                           currentLine.GetExternalCp(cpFirst),
                           dcp,
                           glyphRun
                           )
                    );
                }                   
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("EnumText", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            
            return lserr;
        }
        internal unsafe LsErr DrawTextRun(
            IntPtr          pols,               // Line Layout context
            Plsrun          plsrun,             // plsrun
            ref LSPOINT     ptText,             // [in] text origin
            char*           pwchText,           // character string
            int*            piCharAdvances,     // char advance widths
            int             cchText,            // text length
            LsTFlow         textFlow,           // text flow
            uint            displayMode,        // draw in transparent or opaque
            ref LSPOINT     ptRun,              // [in] run origin
            ref LsHeights   lsHeights,          // [in] run height
            int             dupRun,             // run length
            ref LSRECT      clipRect            // [in] from DisplayLine's clip rectangle param
            )
        {
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try
            {
                TextMetrics.FullTextLine currentLine = Draw.CurrentLine;
                lsrun = currentLine.GetRun(plsrun);

                GlyphRun glyphRun = ComputeUnshapedGlyphRun(
                    lsrun, 
                    textFlow, 
                    currentLine.Formatter,
                    true,       // origin of the glyph run provided at drawing time                    
                    ptText, 
                    dupRun, 
                    cchText, 
                    pwchText, 
                    piCharAdvances,
                    currentLine.IsJustified
                    );

                if (glyphRun != null)
                {
                    DrawingContext drawingContext = Draw.DrawingContext;

                    Draw.SetGuidelineY(glyphRun.BaselineOrigin.Y);                    

                    try 
                    {
                        _boundingBox.Union(
                            lsrun.DrawGlyphRun(
                                drawingContext, 
                                null,   // draw with the run's foreground brush
                                glyphRun
                                )
                            );
                    }
                    finally
                    {
                        Draw.UnsetGuidelineY();
                    }
                }
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("DrawTextRun", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
            /// <summary>
            /// Get LSRun from plsrun
            /// </summary>
            internal LSRun GetRun(Plsrun plsrun)
            {
                ArrayList lsruns = _lsrunsMainText;

                if (TextStore.IsMarker(plsrun))
                {
                    lsruns = _lsrunsMarkerText;
                }

                plsrun = TextStore.ToIndex(plsrun);

                return (LSRun)(
                    TextStore.IsContent(plsrun) ?
                    lsruns[(int)(plsrun - Plsrun.FormatAnchor)] :
                    TextStore.ControlRuns[(int)plsrun]
                    );
            }
        internal unsafe LsErr EnumTab(
            IntPtr              pols,               // pointer to context
            Plsrun              plsrun,             // plsrun
            int                 cpFirst,            // first cp of the dnode run
            char                *pwchText,          // a single tab character
            char                tabLeader,          // a single tab leader character
            LsTFlow             lstFlow,            // flow direction
            int                 fReverseOrder,      // flag for reverse order enumeration
            int                 fGeometryProvided,  // flag for providing geometry information
            ref LSPOINT         pptStart,           // [in] logical start of the run (iff geometryProvided)
            ref LsHeights       heights,            // [in] height (iff geometryProvided)
            int                 dupRun              // width of the run
            )
        {       
            if (cpFirst < 0)
            {

                return LsErr.None;
            }
        
            LsErr lserr = LsErr.None;
            LSRun lsrun = null;

            try 
            {
                TextMetrics.FullTextLine currentLine = Draw.CurrentLine;
                lsrun = currentLine.GetRun(plsrun);
                GlyphRun glyphRun = null;                
                
                if (lsrun.Type == Plsrun.Text)
                {         


                    int charWidth = 0;
                    lsrun.Shapeable.GetAdvanceWidthsUnshaped(
                        &tabLeader, 
                        1,
                        TextFormatterImp.ToIdeal, 
                        &charWidth
                        );                

                    glyphRun = ComputeUnshapedGlyphRun(
                        lsrun, 
                        lstFlow,
                        currentLine.Formatter,
                        false,      // glyph run origin not provided at enumeration time
                        pptStart, 
                        charWidth, 
                        1, 
                        &tabLeader, 
                        &charWidth,
                        currentLine.IsJustified
                        );

                }

                if (glyphRun != null)
                {                    
                    IndexedGlyphRuns.Add(
                        new IndexedGlyphRun(
                           currentLine.GetExternalCp(cpFirst),
                           1,       // dcp is 1 for a Tab character
                           glyphRun
                           )
                    );                    
                }                
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("EnumTab", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }

            return lserr;
        }
 /// <summary>
 /// Get a text store containing the specified plsrun
 /// </summary>
 internal TextStore StoreFrom(Plsrun plsrun)
 {
     return TextStore.IsMarker(plsrun) ? _markerStore : _store;
 }
 private void SaveException(Exception e, Plsrun plsrun, LSRun lsrun)
 {
     e.Data[ExceptionContext.Key] = new ExceptionContext(e.Data[ExceptionContext.Key], e.StackTrace, plsrun, lsrun);
     _exception = e;
 }
 private void SaveNonCLSException(string methodName, Plsrun plsrun, LSRun lsrun)
 {
     Exception e = new System.Exception(SR.Get(SRID.NonCLSException));
     e.Data[ExceptionContext.Key] = new ExceptionContext(null, methodName, plsrun, lsrun);
     _exception = e;
 }
 public ExceptionContext(object innerContext, string stackTraceOrMethodName, Plsrun plsrun, LSRun lsrun)
 {
     _stackTraceOrMethodName = stackTraceOrMethodName;
     _plsrun = (uint)plsrun;
     _lsrun = lsrun;
     _innerContext = innerContext;
 }
Beispiel #32
0
        /// <summary>
        /// Fetch cached textrun
        /// </summary>
        internal TextRun FetchTextRun(
            FormatSettings settings,
            int cpFetch,
            int cpFirst,
            out int offsetToFirstCp,
            out int runLength
            )
        {
            SpanRider textRunSpanRider = new SpanRider(_textRunVector, _latestPosition, cpFetch);

            _latestPosition = textRunSpanRider.SpanPosition;
            TextRun textRun = (TextRun)textRunSpanRider.CurrentElement;

            if (textRun == null)
            {
                // run not already cached, fetch new run and cache it

                textRun = settings.TextSource.GetTextRun(cpFetch);

                if (textRun.Length < 1)
                {
                    throw new ArgumentOutOfRangeException("textRun.Length", SR.Get(SRID.ParameterMustBeGreaterThanZero));
                }

                Plsrun plsrun = TextRunInfo.GetRunType(textRun);

                if (plsrun == Plsrun.Text || plsrun == Plsrun.InlineObject)
                {
                    TextRunProperties properties = textRun.Properties;

                    if (properties == null)
                    {
                        throw new ArgumentException(SR.Get(SRID.TextRunPropertiesCannotBeNull));
                    }

                    if (properties.FontRenderingEmSize <= 0)
                    {
                        throw new ArgumentException(SR.Get(SRID.PropertyOfClassMustBeGreaterThanZero, "FontRenderingEmSize", "TextRunProperties"));
                    }

                    double realMaxFontRenderingEmSize = Constants.RealInfiniteWidth / Constants.GreatestMutiplierOfEm;

                    if (properties.FontRenderingEmSize > realMaxFontRenderingEmSize)
                    {
                        throw new ArgumentException(SR.Get(SRID.PropertyOfClassCannotBeGreaterThan, "FontRenderingEmSize", "TextRunProperties", realMaxFontRenderingEmSize));
                    }

                    CultureInfo culture = CultureMapper.GetSpecificCulture(properties.CultureInfo);

                    if (culture == null)
                    {
                        throw new ArgumentException(SR.Get(SRID.PropertyOfClassCannotBeNull, "CultureInfo", "TextRunProperties"));
                    }

                    if (properties.Typeface == null)
                    {
                        throw new ArgumentException(SR.Get(SRID.PropertyOfClassCannotBeNull, "Typeface", "TextRunProperties"));
                    }
                }


                //
                // TextRun is specifial to SpanVector because TextRun also encodes position which needs to be
                // consistent with the positions encoded by SpanVector. In run cache, the begining of a span
                // should always correspond to the begining of a cached text run. If the end of the currently fetched
                // run overlaps with the begining of an already cached run, the begining of the cached run needs to be
                // adjusted as well as its span. Because we can't gurantee the correctness of the overlapped range
                // so we'll simply remove the overlapped runs here.
                //

                // Move the rider to the end of the current run
                textRunSpanRider.At(cpFetch + textRun.Length - 1);
                _latestPosition = textRunSpanRider.SpanPosition;

                if (textRunSpanRider.CurrentElement != _textRunVector.Default)
                {
                    // The end overlaps with one or more cached runs, clear the range from the
                    // begining of the current fetched run to the end of the last overlapped cached run.
                    _latestPosition = _textRunVector.SetReference(
                        cpFetch,
                        textRunSpanRider.CurrentPosition + textRunSpanRider.Length - cpFetch,
                        _textRunVector.Default,
                        _latestPosition
                        );
                }

                _latestPosition = _textRunVector.SetReference(cpFetch, textRun.Length, textRun, _latestPosition);

                // Refresh the rider's SpanPosition following previous SpanVector.SetReference calls
                textRunSpanRider.At(_latestPosition, cpFetch);
            }

            // If the TextRun was obtained from the cache, make sure it has the right PixelsPerDip set on its properties.

            if (textRun.Properties != null)
            {
                textRun.Properties.PixelsPerDip = settings.TextSource.PixelsPerDip;
            }

            offsetToFirstCp = textRunSpanRider.CurrentPosition - textRunSpanRider.CurrentSpanStart;
            runLength       = textRunSpanRider.Length;
            Debug.Assert(textRun != null && runLength > 0, "Invalid run!");

            bool isText = textRun is ITextSymbols;

            if (isText)
            {
                // Chop text run to optimal length so we dont spend forever analysing
                // them all at once.

                int looseCharLength = TextStore.TypicalCharactersPerLine - cpFetch + cpFirst;

                if (looseCharLength <= 0)
                {
                    // this line already exceeds typical line length, incremental fetch goes
                    // about a quarter of the typical length.

                    looseCharLength = (int)Math.Round(TextStore.TypicalCharactersPerLine * 0.25);
                }

                if (runLength > looseCharLength)
                {
                    if (TextRunInfo.GetRunType(textRun) == Plsrun.Text)
                    {
                        //
                        // When chopping the run at the typical line length,
                        // - don't chop in between of higher & lower surrogate
                        // - don't chop combining mark away from its base character
                        // - don't chop joiner from surrounding characters
                        //
                        // Starting from the initial chopping point, we look ahead to find a safe position. We stop at
                        // a limit in case the run consists of many combining mark & joiner. That is rare and doesn't make
                        // much sense in shaping already.
                        //

                        CharacterBufferReference charBufferRef = textRun.CharacterBufferReference;

                        // We look ahead by one more line at most. It is not normal to have
                        // so many combining mark or joiner characters in a row. It doesn't make sense to
                        // look further if so.
                        int lookAheadLimit = Math.Min(runLength, looseCharLength + TextStore.TypicalCharactersPerLine);

                        int  sizeOfChar = 0;
                        int  endOffset  = 0;
                        bool canBreakAfterPrecedingChar = false;

                        for (endOffset = looseCharLength - 1; endOffset < lookAheadLimit; endOffset += sizeOfChar)
                        {
                            CharacterBufferRange charString = new CharacterBufferRange(
                                charBufferRef.CharacterBuffer,
                                charBufferRef.OffsetToFirstChar + offsetToFirstCp + endOffset,
                                runLength - endOffset
                                );

                            int ch = Classification.UnicodeScalar(charString, out sizeOfChar);

                            // We can only safely break if the preceding char is not a joiner character (i.e. can-break-after),
                            // and the current char is not combining or joiner (i.e. can-break-before).
                            if (canBreakAfterPrecedingChar && !Classification.IsCombining(ch) && !Classification.IsJoiner(ch))
                            {
                                break;
                            }

                            canBreakAfterPrecedingChar = !Classification.IsJoiner(ch);
                        }

                        looseCharLength = Math.Min(runLength, endOffset);
                    }

                    runLength = looseCharLength;
                }
            }


            Debug.Assert(

                // valid run found
                runLength > 0

                // non-text run always fetched at run start
                && (isText ||
                    textRunSpanRider.CurrentSpanStart - textRunSpanRider.CurrentPosition == 0)

                // span rider of both text and format point to valid position
                && (textRunSpanRider.Length > 0 && textRunSpanRider.CurrentElement != null),

                "Text run fetching error!"
                );

            return(textRun);
        }
Beispiel #33
0
        /// <summary>
        /// Constructing a textrun info
        /// </summary> 
        /// <param name="charBufferRange">characte buffer range for the run</param>
        /// <param name="textRunLength">textrun length</param> 
        /// <param name="offsetToFirstCp">character offset to run first cp</param> 
        /// <param name="textRun">text run</param>
        /// <param name="lsRunType">the internal LS run type </param> 
        /// <param name="charFlags">character attribute flags</param>
        /// <param name="digitCulture">digit culture for the run</param>
        /// <param name="contextualSubstitution">contextual number substitution for the run</param>
        /// <param name="symbolTypeface">if true, indicates a text run in a symbol (i.e., non-Unicode) font</param> 
        /// <param name="modifierScope">The current TextModifier scope for this TextRunInfo</param>
        internal TextRunInfo( 
            CharacterBufferRange charBufferRange, 
            int                  textRunLength,
            int                  offsetToFirstCp, 
            TextRun              textRun,
            Plsrun               lsRunType,
            ushort               charFlags,
            CultureInfo          digitCulture, 
            bool                 contextualSubstitution,
            bool                 symbolTypeface, 
            TextModifierScope    modifierScope 
            )
        { 
            _charBufferRange = charBufferRange;
            _textRunLength = textRunLength;
            _offsetToFirstCp = offsetToFirstCp;
            _textRun = textRun; 
            _plsrun = lsRunType;
            _charFlags = charFlags; 
            _digitCulture = digitCulture; 
            _runFlags = 0;
            _modifierScope = modifierScope; 

            if (contextualSubstitution)
            {
                _runFlags |= (ushort)RunFlags.ContextualSubstitution; 
            }
 
            if (symbolTypeface) 
            {
                _runFlags |= (ushort)RunFlags.IsSymbol; 
            }
        }