private void UpdateCachedObjects(Graphics g) { using (new PerfCheck("UpdateCachedObjects")) { using (new PerfCheck("ScriptItemize")) { RTTextbox.ScriptItemize(); } using (new PerfCheck("Flow")) { FlowContext flowContext = new FlowContext(Width, FlowHeight); flowContext.LineLimit = LineLimit; flowContext.CharTrimLastLine = CharTrimLastLine; m_cachedrtparagraphs = LineBreaker.Flow(RTTextbox, g, FontCache, flowContext, keepLines: true, out m_height); } } }
internal static float MeasureFullHeight(TextBox textBox, Graphics g, FontCache fontCache, FlowContext flowContext, out float contentHeight) { if (flowContext.Width <= 0f) { contentHeight = 0f; return(0f); } FlowContext flowContext2 = flowContext.Clone(); flowContext2.Reset(); flowContext2.Height = float.MaxValue; float num = 0f; if (textBox.VerticalText) { flowContext2.LineLimit = false; float width = 0f; float nextWidth = 0f; float num2 = 0f; float num3 = flowContext.Height; float num4 = 0f; if (flowContext.Height == float.MaxValue) { num3 = 0f; } num2 = (contentHeight = LineBreaker.FlowVertical(textBox, g, fontCache, flowContext2, out width, out nextWidth)); num = width; num4 = width; bool flag = flowContext2.CharTrimmedRunWidth > 0; float num5 = 0f; while (num2 < flowContext.Width && width > num3) { flowContext2.Reset(); flowContext2.Height = Math.Max(nextWidth, num3); flowContext2.Width = float.MaxValue; num2 = LineBreaker.FlowVertical(textBox, g, fontCache, flowContext2, out width, out nextWidth); if (num2 < flowContext.Width) { num5 = num2 - contentHeight; if (num2 <= contentHeight || num5 <= 0.1f) { if (flag) { contentHeight = num2; num = flowContext2.Height; break; } if (flowContext2.CharTrimmedRunWidth <= 0) { break; } } contentHeight = num2; num = flowContext2.Height; num4 = width; } else { num5 = num - flowContext2.Height; if (!(num5 > 0.1f)) { break; } nextWidth = flowContext2.Height + (num - flowContext2.Height) / 2f; contentHeight = num2; width = num4; } flag = (flowContext2.CharTrimmedRunWidth > 0); } } else { LineBreaker.Flow(textBox, g, fontCache, flowContext2, keepLines: false, out contentHeight); num = contentHeight; } return(num); }
internal static List <Paragraph> Flow(TextBox textBox, Graphics g, FontCache fontCache, FlowContext flowContext, bool keepLines, out float height) { List <Paragraph> list = null; float dpiX = g.DpiX; Win32DCSafeHandle win32DCSafeHandle = new Win32DCSafeHandle(g.GetHdc(), ownsHandle: false); try { return(Flow(textBox, win32DCSafeHandle, dpiX, fontCache, flowContext, keepLines, out height)); } finally { fontCache.ResetGraphics(); if (!win32DCSafeHandle.IsInvalid) { g.ReleaseHdc(); } } }
internal static List <Paragraph> Flow(TextBox textBox, Win32DCSafeHandle hdc, float dpiX, FontCache fontCache, FlowContext flowContext, bool keepLines, out float height) { if (flowContext.Height <= 0f || flowContext.Width <= 0f) { height = 0f; return(null); } int num = TextBox.ConvertToPixels(flowContext.ContentOffset, dpiX); int contentOffset = num; TextBoxContext context = flowContext.Context; RPLFormat.Directions direction = textBox.TextBoxProps.Direction; List <Paragraph> list = new List <Paragraph>(); Win32ObjectSafeHandle win32ObjectSafeHandle = Win32.SelectObject(hdc, Win32ObjectSafeHandle.Zero); SizeF flowContextSize; if (!textBox.VerticalText) { flowContextSize = new SizeF(TextBox.ConvertToPixels(flowContext.Width, dpiX), TextBox.ConvertToPixels(flowContext.Height, dpiX)); } else { flowContext.VerticalCanGrow = textBox.TextBoxProps.CanGrow; flowContextSize = new SizeF(TextBox.ConvertToPixels(flowContext.Height, dpiX), TextBox.ConvertToPixels(flowContext.Width, dpiX)); } fontCache.WritingMode = textBox.TextBoxProps.WritingMode; try { while (context.ParagraphIndex < textBox.Paragraphs.Count) { Paragraph paragraph = textBox.Paragraphs[context.ParagraphIndex]; paragraph.OffsetY = num; bool num2 = FlowParagraph(paragraph, direction, hdc, dpiX, fontCache, flowContext, keepLines, flowContextSize, ref contentOffset); num += paragraph.Height; if (!keepLines) { paragraph.TextLines = null; } if (!num2) { break; } list.Add(paragraph); if ((float)num >= flowContextSize.Height) { if (paragraph.AtEndOfParagraph(context)) { context.IncrementParagraph(); } break; } context.IncrementParagraph(); } if ((float)num < flowContextSize.Height) { flowContext.AtEndOfTextBox = true; } } finally { if (!win32ObjectSafeHandle.IsInvalid) { Win32.SelectObject(hdc, win32ObjectSafeHandle).SetHandleAsInvalid(); win32ObjectSafeHandle.SetHandleAsInvalid(); } } height = TextBox.ConvertToMillimeters(num, dpiX); flowContext.ContentOffset = TextBox.ConvertToMillimeters(contentOffset, dpiX); return(list); }
private static void FoldLine(Paragraph paragraph, TextLine line, Win32DCSafeHandle hdc, FontCache fontCache, FlowContext flowContext, bool wordTrim, Stack <int> lineRunsIndex, Stack <int> lineRunsCharIndex, float maxWidth, int lineIndents) { int count = line.LogicalRuns.Count; float num = 0f; for (int i = 0; i < count; i++) { num += (float)line.LogicalRuns[i].GetWidth(hdc, fontCache); } int num2 = -1; bool flag = false; for (int num3 = count - 1; num3 >= 0; num3--) { TextRun textRun = line.LogicalRuns[num3]; num -= (float)textRun.GetWidth(hdc, fontCache); SCRIPT_LOGATTR?nextCharLogAttr = null; if (num3 != count - 1) { TextRun textRun2 = line.LogicalRuns[num3 + 1]; if (textRun2.CharacterCount > 0) { nextCharLogAttr = textRun2.ScriptLogAttr[0]; } } if (!textRun.IsPlaceholderTextRun) { flag = true; int num4 = 0; num4 = ((!wordTrim) ? FindFoldTextPosition_CharacterTrim(textRun, hdc, fontCache, maxWidth - num) : FindFoldTextPosition_TextRunTrim(textRun, hdc, fontCache, maxWidth - num, nextCharLogAttr)); if (num4 > 0) { FoldLineAt(line, num3, num4, flowContext.Context, lineRunsIndex, lineRunsCharIndex); return; } } else if (num2 > 0 && textRun.TextRunProperties.IndexInParagraph != num2) { flag = true; } num2 = textRun.TextRunProperties.IndexInParagraph; } if (line.LogicalRuns.Count > 1) { if (!flag) { return; } int num5; for (num5 = line.LogicalRuns.Count - 1; num5 > 0; num5--) { flowContext.Context.TextRunIndex = lineRunsIndex.Pop(); flowContext.Context.TextRunCharacterIndex = lineRunsCharIndex.Pop(); TextRun textRun3 = line.LogicalRuns[num5]; if (!textRun3.IsPlaceholderTextRun || textRun3.CharacterIndexInOriginal == 0) { break; } } line.LogicalRuns.RemoveRange(num5, line.LogicalRuns.Count - num5); } else { if (!flag) { return; } int num6 = 1; if (maxWidth > 0f) { flowContext.ForcedCharTrim = true; if (flowContext.VerticalCanGrow) { num6 = FindWidthToBreakPosition(line.LogicalRuns[0], hdc, fontCache, maxWidth, out int width); flowContext.CharTrimmedRunWidth = Math.Max(flowContext.CharTrimmedRunWidth, width + lineIndents); } else { num6 = FindFoldTextPosition_CharacterTrim(line.LogicalRuns[0], hdc, fontCache, maxWidth); } if (num6 == 0) { num6 = 1; } } else if (line.FirstLine && paragraph.ParagraphProps.HangingIndent > 0f) { num6 = 0; if (flowContext.Updatable) { paragraph.Updated = true; } } FoldLineAt(line, 0, num6, flowContext.Context, lineRunsIndex, lineRunsCharIndex); } }
internal static List <Paragraph> Flow(TextBox textBox, Graphics g, FontCache fontCache, FlowContext flowContext, bool keepLines) { float height; return(Flow(textBox, g, fontCache, flowContext, keepLines, out height)); }
private static bool GetLine(Paragraph paragraph, TextLine line, Win32DCSafeHandle hdc, FontCache fontCache, FlowContext flowContext, float left, float right, float height, Stack <int> lineRunsIndex, Stack <int> lineRunsCharIndex, int lineIndents) { float num = right - left; float num2 = left; bool newLine = false; int num3 = 0; do { lineRunsIndex.Push(flowContext.Context.TextRunIndex); lineRunsCharIndex.Push(flowContext.Context.TextRunCharacterIndex); TextRun subRunForLine = paragraph.GetSubRunForLine(flowContext.Context, ref newLine); if (subRunForLine == null) { break; } line.LogicalRuns.Add(subRunForLine); int width = subRunForLine.GetWidth(hdc, fontCache); num3 = Math.Max(subRunForLine.GetWidth(hdc, fontCache, isAtLineEnd: true) - width, num3); num2 += (float)width; if (!(num2 + (float)num3 > right)) { continue; } bool flag = flowContext.WordTrim; if (!flowContext.LineLimit && flag) { if ((float)line.GetHeight(hdc, fontCache) >= height) { flag = false; } line.ResetHeight(); } if (!subRunForLine.IsPlaceholderTextRun) { FoldLine(paragraph, line, hdc, fontCache, flowContext, flag, lineRunsIndex, lineRunsCharIndex, num - (float)num3, lineIndents); break; } lineRunsIndex.Push(flowContext.Context.TextRunIndex); lineRunsCharIndex.Push(flowContext.Context.TextRunCharacterIndex); bool flag2 = true; TextRun subRunForLine2 = paragraph.GetSubRunForLine(flowContext.Context, ref newLine); if (subRunForLine2 != null) { flag2 = (subRunForLine.TextRunProperties.IndexInParagraph < subRunForLine2.TextRunProperties.IndexInParagraph); } flowContext.Context.TextRunIndex = lineRunsIndex.Pop(); flowContext.Context.TextRunCharacterIndex = lineRunsCharIndex.Pop(); if (flag2) { FoldLine(paragraph, line, hdc, fontCache, flowContext, flag, lineRunsIndex, lineRunsCharIndex, num - (float)num3, lineIndents); break; } }while (!newLine); if (line.LogicalRuns.Count == 0) { return(false); } return(true); }
private static bool FlowParagraph(Paragraph paragraph, RPLFormat.Directions direction, Win32DCSafeHandle hdc, float dpiX, FontCache fontCache, FlowContext flowContext, bool keepLines, SizeF flowContextSize, ref int contentOffset) { List <TextLine> list = new List <TextLine>(); TextBoxContext context = flowContext.Context; int num = paragraph.OffsetY; paragraph.ProcessedEmptyParagraph = false; bool flag = false; IParagraphProps paragraphProps = paragraph.ParagraphProps; if (!flowContext.Updatable || !paragraph.Updated) { flag = (context.TextRunIndex == 0 && context.TextRunCharacterIndex == 0); } if (flag) { num += TextBox.ConvertToPixels(paragraphProps.SpaceBefore, dpiX); if ((float)num >= flowContextSize.Height) { paragraph.Height = num - paragraph.OffsetY; return(false); } } int num2 = contentOffset; float leftIndent = 0f; float rightIndent = 0f; float hangingIndent = 0f; paragraph.GetParagraphIndents(direction, dpiX, out leftIndent, out rightIndent, out hangingIndent); Stack <int> stack = null; Stack <int> stack2 = null; TextLine textLine = null; while (true) { float num3 = leftIndent; float num4 = rightIndent; if (flag) { if (direction == RPLFormat.Directions.LTR) { num3 += hangingIndent; } else { num4 += hangingIndent; } } stack = new Stack <int>(); stack2 = new Stack <int>(); textLine = new TextLine(); if (flag) { textLine.Prefix = CreateLinePrefix(paragraph, direction); textLine.FirstLine = true; } if (!GetLine(paragraph, textLine, hdc, fontCache, flowContext, num3, flowContextSize.Width - num4, flowContextSize.Height - (float)num, stack, stack2, (int)(num3 + num4))) { if (list.Count > 0) { list[list.Count - 1].LastLine = true; } num += TextBox.ConvertToPixels(paragraphProps.SpaceAfter, dpiX); break; } if (keepLines) { textLine.ScriptLayout(hdc, fontCache); } num += textLine.GetHeight(hdc, fontCache); list.Add(textLine); num2 = num; if ((float)num >= flowContextSize.Height) { break; } flag = false; } paragraph.Height = num - paragraph.OffsetY; if ((float)num > flowContextSize.Height) { if (list.Count > 0 && (float)num2 > flowContextSize.Height) { TextLine textLine2 = list[list.Count - 1]; int textRunIndex = 0; int textRunCharacterIndex = 0; while (stack.Count > 0) { textRunIndex = stack.Pop(); } while (stack2.Count > 0) { textRunCharacterIndex = stack2.Pop(); } if (flowContext.LineLimit) { context.TextRunIndex = textRunIndex; context.TextRunCharacterIndex = textRunCharacterIndex; list.RemoveAt(list.Count - 1); flowContext.OmittedLineHeight = TextBox.ConvertToMillimeters(textLine2.GetHeight(hdc, fontCache), dpiX); if (textLine2.FirstLine) { num2 -= TextBox.ConvertToPixels(paragraphProps.SpaceBefore, dpiX); } } else { TextBoxContext textBoxContext = context.Clone(); textBoxContext.TextRunIndex = textRunIndex; textBoxContext.TextRunCharacterIndex = textRunCharacterIndex; flowContext.ClipContext = textBoxContext; } num2 -= textLine2.GetHeight(hdc, fontCache); } paragraph.AdvanceToNextRun(context, skipEmptyRuns: false); paragraph.AdvanceToNextRun(flowContext.ClipContext, skipEmptyRuns: false); if (list.Count > 0) { if (flowContext.ClipContext == null && paragraph.AtEndOfParagraph(context)) { contentOffset = num; } else { contentOffset = num2; } paragraph.TextLines = list; return(true); } paragraph.TextLines = null; if (paragraph.AtEndOfParagraph(context)) { contentOffset = num; } return(false); } paragraph.AdvanceToNextRun(context); paragraph.TextLines = list; contentOffset = num; return(true); }
internal static float FlowVertical(TextBox textBox, Graphics g, FontCache fontCache, FlowContext flowContext, out float width, out float nextWidth) { width = (nextWidth = 0f); List <Paragraph> list = null; int num = 0; int val = int.MaxValue; int num2 = 0; float height = 0f; int num3 = 0; List <TextLine> list2 = null; float dpiX = g.DpiX; Win32DCSafeHandle win32DCSafeHandle = new Win32DCSafeHandle(g.GetHdc(), ownsHandle: false); if (textBox.VerticalText) { flowContext.VerticalCanGrow = textBox.TextBoxProps.CanGrow; num3 = TextBox.ConvertToPixels(flowContext.Height, dpiX); } else { num3 = TextBox.ConvertToPixels(flowContext.Width, dpiX); } try { list = Flow(textBox, win32DCSafeHandle, dpiX, fontCache, flowContext, keepLines: true, out height); if (list != null) { for (int i = 0; i < list.Count; i++) { list2 = list[i].TextLines; if (list2 != null) { float leftIndent = 0f; float rightIndent = 0f; float hangingIndent = 0f; float num4 = 0f; RPLFormat.Directions direction = textBox.TextBoxProps.Direction; list[i].GetParagraphIndents(direction, dpiX, out leftIndent, out rightIndent, out hangingIndent); num4 = leftIndent + rightIndent; if (list2[0].FirstLine) { num4 += hangingIndent; } num2 = Math.Max(num2, (int)num4); for (int j = 0; j < list2.Count; j++) { num = Math.Max(num, list2[j].GetWidth(win32DCSafeHandle, fontCache, useVisualRunsIfAvailable: false) + (int)num4); val = Math.Min(val, list2[j].GetWidth(win32DCSafeHandle, fontCache, useVisualRunsIfAvailable: false) + (int)num4); } list[i].TextLines = null; } } } val = Math.Max(val, num2); if (num > 0) { int num5 = 0; if (flowContext.VerticalCanGrow && flowContext.ForcedCharTrim) { num5 = flowContext.CharTrimmedRunWidth; } else { num5 = (num - val) / 2; if (num5 == 0) { num5 = num / 2; } else { num5 += val; if (num5 >= num3) { num5 /= 2; } } } width = TextBox.ConvertToMillimeters(num, dpiX); nextWidth = TextBox.ConvertToMillimeters(num5, dpiX); return(height); } return(height); } finally { fontCache.ResetGraphics(); if (!win32DCSafeHandle.IsInvalid) { g.ReleaseHdc(); } } }