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