diff options
author | Karl <karl@scowencomputers.co.nz> | 2015-09-10 07:37:57 +0300 |
---|---|---|
committer | Karl <karl@scowencomputers.co.nz> | 2020-01-13 06:42:44 +0300 |
commit | 1821cc8adfd3e1dc135c9dd7cb40f86a3058e96b (patch) | |
tree | 6c1b99153ceba09d97bc9d7dd3315cfc4a166c0b /mcs/class | |
parent | be446f04f34b6ad1ff53e67eee0e4aa08f072dfc (diff) |
RichTextBox: Cache dpi
The dpi isn't likely to change during the lifetime of the object, so is relatively safe to cache.
Creating a Graphics object each time the dpi is wanted when reading RTF is also rather silly performance-wise.
Even worse, when generating RTF it can cause a recalc, which can mean that some lines <= end_line don't exist.
Diffstat (limited to 'mcs/class')
-rw-r--r-- | mcs/class/System.Windows.Forms/System.Windows.Forms/RichTextBox.cs | 350 |
1 files changed, 173 insertions, 177 deletions
diff --git a/mcs/class/System.Windows.Forms/System.Windows.Forms/RichTextBox.cs b/mcs/class/System.Windows.Forms/System.Windows.Forms/RichTextBox.cs index f553bc498b4..cadee537a96 100644 --- a/mcs/class/System.Windows.Forms/System.Windows.Forms/RichTextBox.cs +++ b/mcs/class/System.Windows.Forms/System.Windows.Forms/RichTextBox.cs @@ -68,6 +68,8 @@ namespace System.Windows.Forms { private bool enable_auto_drag_drop; private RichTextBoxLanguageOptions language_option; private bool rich_text_shortcuts_enabled; + + private readonly float dpi; // Store the dpi so we don't have to create a Graphics object to calculate this frequently. Needed to read or write RTF sizes. //private Color selection_back_color; // We don't actually need this now. #endregion // Local Variables @@ -108,6 +110,9 @@ namespace System.Windows.Forms { base.VScrolled += new EventHandler(RichTextBox_VScrolled); SetStyle (ControlStyles.StandardDoubleClick, false); + + using (Graphics g = CreateGraphics()) + dpi = (g.DpiX + g.DpiY) / 2; } #endregion // Public Constructors @@ -1843,15 +1848,13 @@ namespace System.Windows.Forms { case RTF.Minor.SuperScript: { FlushText (rtf, false); - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_char_offset = (int) (((float) rtf.Param / 144.0F) * g.DpiX + 0.5F); + rtf_style.rtf_char_offset = (int) (((float) rtf.Param / 144.0F) * dpi + 0.5F); break; } case RTF.Minor.SubScript: { FlushText (rtf, false); - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_char_offset = -(int) (((float) rtf.Param / 144.0F) * g.DpiX + 0.5F); + rtf_style.rtf_char_offset = -(int) (((float) rtf.Param / 144.0F) * dpi + 0.5F); break; } } @@ -1873,23 +1876,19 @@ namespace System.Windows.Forms { break; case RTF.Minor.TabPos: - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_par_tab_stops.Add((int) (((float) rtf.Param / 1440.0F) * g.DpiX + 0.5F)); + rtf_style.rtf_par_tab_stops.Add((int) (((float) rtf.Param / 1440.0F) * dpi + 0.5F)); break; case RTF.Minor.LeftIndent: - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_par_line_left_indent = (int) (((float) rtf.Param / 1440.0F) * g.DpiX + 0.5F); + rtf_style.rtf_par_line_left_indent = (int) (((float) rtf.Param / 1440.0F) * dpi + 0.5F); break; case RTF.Minor.FirstIndent: - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_par_first_line_indent = (int) (((float) rtf.Param / 1440.0F) * g.DpiX + 0.5F); + rtf_style.rtf_par_first_line_indent = (int) (((float) rtf.Param / 1440.0F) * dpi + 0.5F); break; case RTF.Minor.RightIndent: - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_par_line_right_indent = (int) (((float) rtf.Param / 1440.0F) * g.DpiX + 0.5F); + rtf_style.rtf_par_line_right_indent = (int) (((float) rtf.Param / 1440.0F) * dpi + 0.5F); break; case RTF.Minor.QuadCenter: @@ -1913,13 +1912,11 @@ namespace System.Windows.Forms { break; case RTF.Minor.SpaceAfter: - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_par_spacing_after = (int) (((float) rtf.Param / 1440.0F) * g.DpiX + 0.5F); + rtf_style.rtf_par_spacing_after = (int) (((float) rtf.Param / 1440.0F) * dpi + 0.5F); break; case RTF.Minor.SpaceBefore: - using (Graphics g = CreateGraphics ()) - rtf_style.rtf_par_spacing_before = (int) (((float) rtf.Param / 1440.0F) * g.DpiX + 0.5F); + rtf_style.rtf_par_spacing_before = (int) (((float) rtf.Param / 1440.0F) * dpi + 0.5F); break; } @@ -1941,7 +1938,8 @@ namespace System.Windows.Forms { case RTF.Minor.Row: case RTF.Minor.Line: case RTF.Minor.Par: { - FlushText(rtf, true); + if (Multiline) + FlushText(rtf, true); break; } @@ -2491,201 +2489,199 @@ namespace System.Windows.Forms { prev_left_indent = left_indent; right_indent = line.RightIndent; - using (Graphics g = CreateGraphics ()) { - // Emit initial paragraph settings - sb.Append("\\pard"); // Reset to default paragraph properties - switch (line.alignment) { - case HorizontalAlignment.Left: - sb.Append("\\ql"); - break; - case HorizontalAlignment.Center: - sb.Append("\\qc"); - break; - case HorizontalAlignment.Right: - sb.Append("\\qr"); - break; + // Emit initial paragraph settings + sb.Append("\\pard"); // Reset to default paragraph properties + switch (line.alignment) { + case HorizontalAlignment.Left: + sb.Append("\\ql"); + break; + case HorizontalAlignment.Center: + sb.Append("\\qc"); + break; + case HorizontalAlignment.Right: + sb.Append("\\qr"); + break; + } + if (line.spacing_after != 0) { + sb.Append("\\sa"); + sb.Append((line.spacing_after / dpi) * 1440); + } + if (line.spacing_before != 0) { + sb.Append("\\sb"); + sb.Append((line.spacing_before / dpi) * 1440); + } + if (left_indent != 0) { + sb.Append("\\li"); + sb.Append(((left_indent) / dpi) * 1440); + } + if (first_line_indent != 0) { + sb.Append("\\fi"); + sb.Append((first_line_indent / dpi) * 1440); + } + if (line.right_indent != 0) { + sb.Append("\\ri"); + sb.Append((line.right_indent / dpi) * 1440); + } + EmitRTFFontProperties(sb, -1, fonts.IndexOf(tag.Font.Name), null, tag.Font); // Font properties + sb.Append(" "); // Space separator + + while (line_no <= end_line.line_no) { + line = document.GetLine(line_no); + line.Streamline(document.Lines); + tag = LineTag.FindTag(line, pos); + + if (line_no != end_line.line_no) { + line_len = line.text.Length; + } else { + line_len = end_pos; } - if (line.spacing_after != 0) { + + length = sb.Length; + if (line.Alignment != line_alignment) { + line_alignment = line.Alignment; + switch (line_alignment) { + case HorizontalAlignment.Left: + sb.Append("\\ql"); + break; + case HorizontalAlignment.Center: + sb.Append("\\qc"); + break; + case HorizontalAlignment.Right: + sb.Append("\\qr"); + break; + } + } + + if (line.spacing_after != spacing_after) { + spacing_after = line.spacing_after; sb.Append("\\sa"); - sb.Append((line.spacing_after / g.DpiX) * 1440); + sb.Append((int) ((spacing_after / dpi) * 1440)); } - if (line.spacing_before != 0) { + + if (line.spacing_before != spacing_before) { + spacing_before = line.spacing_before; sb.Append("\\sb"); - sb.Append((line.spacing_before / g.DpiX) * 1440); + sb.Append((int) ((spacing_before / dpi) * 1440)); } - if (left_indent != 0) { + + first_line_indent = -line.HangingIndent; + left_indent = line.Indent - first_line_indent; + + if (prev_left_indent != left_indent) { + prev_left_indent = left_indent; sb.Append("\\li"); - sb.Append(((left_indent) / g.DpiX) * 1440); + sb.Append((left_indent / dpi) * 1440); } - if (first_line_indent != 0) { + + if (prev_first_line_indent != first_line_indent) { + prev_first_line_indent = first_line_indent; sb.Append("\\fi"); - sb.Append((first_line_indent / g.DpiX) * 1440); + sb.Append((first_line_indent / dpi) * 1440); } - if (line.right_indent != 0) { + + if (line.right_indent != right_indent) { + right_indent = line.right_indent; sb.Append("\\ri"); - sb.Append((line.right_indent / g.DpiX) * 1440); + sb.Append((right_indent / dpi) * 1440); } - EmitRTFFontProperties(sb, -1, fonts.IndexOf(tag.Font.Name), null, tag.Font); // Font properties - sb.Append(" "); // Space separator - while (line_no <= end_line.line_no) { - line = document.GetLine(line_no); - line.Streamline(document.Lines); - tag = LineTag.FindTag(line, pos); + if (length != sb.Length) { + sb.Append(" "); + } - if (line_no != end_line.line_no) { - line_len = line.text.Length; - } else { - line_len = end_pos; + while (pos < line_len && tag != null) { + length = sb.Length; + + if (tag.Font != font) { + EmitRTFFontProperties(sb, fonts.IndexOf(font.Name), fonts.IndexOf(tag.Font.Name), font, tag.Font); + font = tag.Font; } - length = sb.Length; - if (line.Alignment != line_alignment) { - line_alignment = line.Alignment; - switch (line_alignment) { - case HorizontalAlignment.Left: - sb.Append("\\ql"); + if (tag.Color != color) { + color = tag.Color; + if (color != Color.Empty) + sb.Append(String.Format("\\cf{0}", colors.IndexOf(color) + 1)); + else + sb.Append("\\cf0"); + } + + if (tag.BackColor != back_color) { + back_color = tag.BackColor; + if (back_color != Color.Empty) + sb.Append(String.Format("\\cb{0}", colors.IndexOf(back_color) + 1)); + else + sb.Append("\\cb0"); + } + + if (tag.TextPosition != text_position) { + text_position = tag.TextPosition; + switch (tag.TextPosition) { + case TextPositioning.Normal: + sb.Append("\\nosupersub"); break; - case HorizontalAlignment.Center: - sb.Append("\\qc"); + case TextPositioning.Subscript: + sb.Append("\\sub"); break; - case HorizontalAlignment.Right: - sb.Append("\\qr"); + case TextPositioning.Superscript: + sb.Append("\\super"); break; } } - - if (line.spacing_after != spacing_after) { - spacing_after = line.spacing_after; - sb.Append("\\sa"); - sb.Append((int) ((spacing_after / g.DpiX) * 1440)); - } - - if (line.spacing_before != spacing_before) { - spacing_before = line.spacing_before; - sb.Append("\\sb"); - sb.Append((int) ((spacing_before / g.DpiX) * 1440)); - } - - first_line_indent = -line.HangingIndent; - left_indent = line.Indent - first_line_indent; - - if (prev_left_indent != left_indent) { - prev_left_indent = left_indent; - sb.Append("\\li"); - sb.Append((left_indent / g.DpiX) * 1440); - } - if (prev_first_line_indent != first_line_indent) { - prev_first_line_indent = first_line_indent; - sb.Append("\\fi"); - sb.Append((first_line_indent / g.DpiX) * 1440); + if (tag.CharOffset != char_offset) { + char_offset = tag.CharOffset; + if (char_offset >= 0) { + sb.Append("\\up"); + sb.Append((int) ((char_offset / dpi) * 144)); + } else { + sb.Append("\\dn"); + sb.Append(-(int) ((char_offset / dpi) * 144)); + } } - if (line.right_indent != right_indent) { - right_indent = line.right_indent; - sb.Append("\\ri"); - sb.Append((right_indent / g.DpiX) * 1440); + if (tag.Visible != visible) { + visible = tag.Visible; + if (visible) + sb.Append("\\v0"); + else + sb.Append("\\v"); } if (length != sb.Length) { - sb.Append(" "); + sb.Append(" "); // Emit space to separate keywords from text } - while (pos < line_len && tag != null) { - length = sb.Length; - - if (tag.Font != font) { - EmitRTFFontProperties(sb, fonts.IndexOf(font.Name), fonts.IndexOf(tag.Font.Name), font, tag.Font); - font = tag.Font; - } - - if (tag.Color != color) { - color = tag.Color; - if (color != Color.Empty) - sb.Append(String.Format("\\cf{0}", colors.IndexOf(color) + 1)); - else - sb.Append("\\cf0"); - } - - if (tag.BackColor != back_color) { - back_color = tag.BackColor; - if (back_color != Color.Empty) - sb.Append(String.Format("\\cb{0}", colors.IndexOf(back_color) + 1)); - else - sb.Append("\\cb0"); - } - - if (tag.TextPosition != text_position) { - text_position = tag.TextPosition; - switch (tag.TextPosition) { - case TextPositioning.Normal: - sb.Append("\\nosupersub"); - break; - case TextPositioning.Subscript: - sb.Append("\\sub"); - break; - case TextPositioning.Superscript: - sb.Append("\\super"); - break; - } - } - - if (tag.CharOffset != char_offset) { - char_offset = tag.CharOffset; - if (char_offset >= 0) { - sb.Append("\\up"); - sb.Append((int) ((char_offset / g.DpiX) * 144)); - } else { - sb.Append("\\dn"); - sb.Append(-(int) ((char_offset / g.DpiX) * 144)); - } - } - - if (tag.Visible != visible) { - visible = tag.Visible; - if (visible) - sb.Append("\\v0"); - else - sb.Append("\\v"); - } - - if (length != sb.Length) { - sb.Append(" "); // Emit space to separate keywords from text - } - - // Emit the string itself - if (line_no != end_line.line_no) { - EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1)); + // Emit the string itself + if (line_no != end_line.line_no) { + EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1)); + } else { + if (end_pos < (tag.Start + tag.Length - 1)) { + // Emit partial tag only, end_pos is inside this tag + EmitRTFText(sb, tag.Line.text.ToString(pos, end_pos - pos)); } else { - if (end_pos < (tag.Start + tag.Length - 1)) { - // Emit partial tag only, end_pos is inside this tag - EmitRTFText(sb, tag.Line.text.ToString(pos, end_pos - pos)); - } else { - EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1)); - } + EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1)); } - - pos = tag.Start + tag.Length - 1; - tag = tag.Next; } - if (pos >= line.text.Length) { - if (line.ending != LineEnding.Wrap) { - // pos is incremented by the tag length, so it can be after where we want to finish. - // If we're on the last line we don't want to output \par when we're stopping before the end of the line. - if (!(line_no == end_line.line_no && pos > end_pos)) - sb.Append("\\par"); - sb.Append(Environment.NewLine); - } + + pos = tag.Start + tag.Length - 1; + tag = tag.Next; + } + if (pos >= line.text.Length) { + if (line.ending != LineEnding.Wrap) { + // pos is incremented by the tag length, so it can be after where we want to finish. + // If we're on the last line we don't want to output \par when we're stopping before the end of the line. + if (!(line_no == end_line.line_no && pos > end_pos)) + sb.Append("\\par"); + sb.Append(Environment.NewLine); } - pos = 0; - line_no++; } - - sb.Append("}"); - sb.Append(Environment.NewLine); + pos = 0; + line_no++; } + sb.Append("}"); + sb.Append(Environment.NewLine); + return sb; } #endregion // Private Methods |