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 unsafe LsErr GetGlyphCompressionInfoFullMixed( 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 **pplscompressionLeft, // [in/out] fill in left compression amount per priority level on the way out int **pplscompressionRight // [in/out] fill in right compression amount per priority level on the way out ) { 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 CompressGlyphs( plsglyphrunInfo, (int)(em * Constants.MinInterWordCompressionPerEm), pplscompressionLeft, pplscompressionRight ); } catch (Exception e) { SaveException(e, plsrun, lsrun); lserr = LsErr.ClientAbort; } catch { SaveNonCLSException("GetGlyphCompressionInfoFullMixed", plsrun, lsrun); lserr = LsErr.ClientAbort; } return lserr; }
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; }
internal unsafe LsErr GetGlyphPositions( IntPtr pols, // Line Layout context IntPtr* plsplsruns, // array of plsruns int* pcchPlsrun, // array of character count per run int plsrunCount, // number of runs LsDevice device, // on reference or presentation device char* pwchText, // character string ushort* puClusterMap, // character-to-glyph cluster map ushort* puCharProperties, // character properties int cchText, // character count ushort* puGlyphs, // glyph indices uint* piGlyphProperties, // glyph properties int glyphCount, // glyph count LsTFlow textFlow, // text flow direction int* piGlyphAdvances, // [out] glyph advances GlyphOffset* piiGlyphOffsets // [out] glyph offsets ) { LsErr lserr = LsErr.None; LSRun lsrunFirst = null; try { LSRun[] lsruns = RemapLSRuns(plsplsruns, plsrunCount); lsrunFirst = lsruns[0]; bool isRightToLeft = ((lsrunFirst.BidiLevel & 1) != 0); GlyphOffset[] glyphOffset; GlyphTypeface glyphTypeface = lsrunFirst.Shapeable.GlyphTypeFace; DWriteFontFeature[][] fontFeatures; uint[] fontFeatureRanges; LSRun.CompileFeatureSet(lsruns, pcchPlsrun, checked((uint)cchText), out fontFeatures, out fontFeatureRanges); FullText.Formatter.TextAnalyzer.GetGlyphPlacements( (ushort*)pwchText, puClusterMap, (ushort*)puCharProperties, (uint)cchText, puGlyphs, piGlyphProperties, (uint)glyphCount, glyphTypeface.FontDWrite, lsrunFirst.Shapeable.EmSize, TextFormatterImp.ToIdeal, false, isRightToLeft, lsrunFirst.RunProp.CultureInfo, fontFeatures, fontFeatureRanges, FullText.TextFormattingMode, lsrunFirst.Shapeable.ItemProps, Util.PixelsPerDip, piGlyphAdvances, out glyphOffset ); for (int i = 0; i < glyphCount; ++i) { piiGlyphOffsets[i].du = glyphOffset[i].du; piiGlyphOffsets[i].dv = glyphOffset[i].dv; } } catch (Exception e) { SaveException(e, (Plsrun)(plsplsruns[0]), lsrunFirst); lserr = LsErr.ClientAbort; } catch { SaveNonCLSException("GetGlyphPositions", (Plsrun)(plsplsruns[0]), lsrunFirst); lserr = LsErr.ClientAbort; } return lserr; }