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 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;
        }
        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 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;
        }
        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;
        }