internal unsafe LsErr GetGlyphExpansionInfoFullMixed(
            IntPtr              pols,                   // Line Layout context
            LsDevice            device,                 // kind of device
            LsTFlow             textFlow,               // text flow
            LsGlyphRunInfo      *plsglyphrunInfo,       // glyph-based run info
            LsNeighborInfo      *plsneighborInfoLeft,   // left neighbor info
            LsNeighborInfo      *plsneighborInfoRight,  // right neigbor info
            int                 maxPriorityLevel,       // maximum priority level
            int                 **pplsexpansionLeft,    // [in/out] fill in left expansion amount per priority level on the way out
            int                 **pplsexpansionRight,   // [in/out] fill in right expansion amount per priority level on the way out
            LsExpType           *plsexptype,            // [in/out] fill in glyph expansion type for each glyph
            int                 *pduMinInk              // [in/out] fill in glyph minimum expansion for exptAddInkContinuous
            )
        {
            LsErr lserr = LsErr.None;
            Plsrun plsrun = Plsrun.Undefined;
            LSRun lsrun = null;

            try
            {
                Invariant.Assert(maxPriorityLevel == 3);

                plsrun = plsglyphrunInfo->plsrun;
                lsrun = FullText.StoreFrom(plsrun).GetRun(plsrun);
                int em = lsrun.EmSize;

                return ExpandGlyphs(
                    plsglyphrunInfo,
                    (int)(em * Constants.MaxInterWordExpansionPerEm),
                    pplsexpansionLeft,
                    pplsexpansionRight,
                    plsexptype,
                    LsExpType.AddWhiteSpace,    // inter-word expansion type


                    ((lsrun.BidiLevel & 1) == 0 ? LsExpType.AddWhiteSpace : LsExpType.None)
                    );
            }
            catch (Exception e)
            {
                SaveException(e, plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            catch
            {
                SaveNonCLSException("GetGlyphExpansionInfoFullMixed", plsrun, lsrun);
                lserr = LsErr.ClientAbort;
            }
            return lserr;
        }
        private unsafe LsErr ExpandGlyphs(
            LsGlyphRunInfo      *plsglyphrunInfo,
            int                 interWordExpandTo,
            int                 **pplsExpansionLeft,
            int                 **pplsExpansionRight,
            LsExpType           *plsexptype,
            LsExpType           interWordExpansionType,
            LsExpType           interLetterExpansionType
            )
        {
            char* pwch = plsglyphrunInfo->pwch;
            ushort* pgmap = plsglyphrunInfo->rggmap;
            int cchRun = plsglyphrunInfo->cwch;
            int cgiRun = plsglyphrunInfo->cgindex;

            int ich = 0;
            int igi = pgmap[ich];
            int cgi = 0;


            while (ich < cchRun)
            {

                int cch = 1;
                while (ich + cch < cchRun && pgmap[ich + cch] == igi)
                    cch++;


                cgi = (ich + cch == cchRun) ? cgiRun - igi : pgmap[ich + cch] - igi;

                int i, j;


                for (j = 0; j < cch; j++)
                {
                    ushort flags = (ushort)(Classification.CharAttributeOf((int)Classification.GetUnicodeClassUTF16(pwch[ich + j]))).Flags;
                    if ((flags & ((ushort)CharacterAttributeFlags.CharacterSpace)) != 0)
                        break;
                }

                int glyphAdvance = 0;
                for (i = 0; i < cgi; i++)
                {
                    glyphAdvance += plsglyphrunInfo->rgduWidth[igi + i];


                    pplsExpansionLeft[0][igi + i] = 0;
                    pplsExpansionLeft[1][igi + i] = 0;
                    pplsExpansionLeft[2][igi + i] = 0;


                    pplsExpansionRight[0][igi + i] = 0;
                    pplsExpansionRight[1][igi + i] = 0;
                    pplsExpansionRight[2][igi + i] = 0;

                    if (i == cgi - 1)
                    {
                        if (cch == 1 && j < cch)
                        {

                            int expandedBy = Math.Max(0, interWordExpandTo - glyphAdvance);
                            pplsExpansionRight[0][igi + i] = expandedBy;
                            pplsExpansionRight[1][igi + i] = expandedBy * Constants.AcceptableLineStretchability;
                            pplsExpansionRight[2][igi + i] = FullText.FormatWidth;
                            plsexptype[igi + i] = interWordExpansionType;
                        }
                        else
                        {

                            pplsExpansionRight[2][igi + i] = FullText.FormatWidth;
                            plsexptype[igi + i] = interLetterExpansionType;
                        }
                    }
                }

                ich += cch;
                igi += cgi;
            }

            Invariant.Assert(igi == cgiRun);
            return LsErr.None;
        }
        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;
        }