Further optimize wrapping long lines in wxRichTextCtrl
When adding characters to a long word-wrapped line one by one, there was an hotspot in wxString(const wxString&) and wxString::replace. When rendering or getting caret position, each broken line from a long line of text was being processed separately. Before handling each line, some preprocessing is done: replace a character by another character and make uppercase if necessary. Before, this way happening for each line: * make a copy of the whole long string * preprocess that copy of long string * get the needed substring of it Now, we do this in most cases: * get the needed substring of the long string * preprocess that short string
This commit is contained in:
@@ -6819,21 +6819,57 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
|
||||
|
||||
int offset = GetRange().GetStart();
|
||||
|
||||
wxString str = m_text;
|
||||
const bool allSelected = selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd();
|
||||
const bool noneSelected = selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd();
|
||||
|
||||
wxString stringChunk;
|
||||
wxString stringWhole;
|
||||
|
||||
// If nothing or everything is selected, our algorithm does not need stringWhole. It
|
||||
// is enough to preprocess stringChunk only.
|
||||
// In case of partial selection we need to preprocess stringWhole too.
|
||||
if (allSelected || noneSelected)
|
||||
{
|
||||
const wxString* pWholeString = &m_text;
|
||||
if (context.HasVirtualText(this))
|
||||
{
|
||||
if (!context.GetVirtualText(this, str) || str.Length() != m_text.Length())
|
||||
str = m_text;
|
||||
if (context.GetVirtualText(this, stringWhole) && stringWhole.Length() == m_text.Length())
|
||||
pWholeString = &stringWhole;
|
||||
}
|
||||
|
||||
long len = range.GetLength();
|
||||
stringChunk = pWholeString->Mid(range.GetStart() - offset, (size_t) len);
|
||||
|
||||
// Replace line break characters with spaces
|
||||
wxString toRemove = wxRichTextLineBreakChar;
|
||||
stringChunk.Replace(toRemove, wxT(" "));
|
||||
if (textAttr.HasTextEffects() &&
|
||||
(textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||
{
|
||||
stringChunk.MakeUpper();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stringWhole = m_text;
|
||||
if (context.HasVirtualText(this))
|
||||
{
|
||||
if (!context.GetVirtualText(this, stringWhole) || stringWhole.Length() != m_text.Length())
|
||||
stringWhole = m_text;
|
||||
}
|
||||
|
||||
// Replace line break characters with spaces
|
||||
wxString toRemove = wxRichTextLineBreakChar;
|
||||
str.Replace(toRemove, wxT(" "));
|
||||
if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||
str.MakeUpper();
|
||||
stringWhole.Replace(toRemove, wxT(" "));
|
||||
if (textAttr.HasTextEffects() &&
|
||||
(textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||
{
|
||||
stringWhole.MakeUpper();
|
||||
}
|
||||
|
||||
long len = range.GetLength();
|
||||
wxString stringChunk = str.Mid(range.GetStart() - offset, (size_t) len);
|
||||
stringChunk = stringWhole.Mid(range.GetStart() - offset, (size_t) len);
|
||||
}
|
||||
|
||||
// Test for the optimized situations where all is selected, or none
|
||||
// is selected.
|
||||
@@ -6903,12 +6939,12 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
|
||||
// TODO: new selection code
|
||||
|
||||
// (a) All selected.
|
||||
if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
|
||||
if (allSelected)
|
||||
{
|
||||
DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, true);
|
||||
}
|
||||
// (b) None selected.
|
||||
else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
|
||||
else if (noneSelected)
|
||||
{
|
||||
// Draw all unselected
|
||||
DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false);
|
||||
@@ -6918,6 +6954,8 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
|
||||
// (c) Part selected, part not
|
||||
// Let's draw unselected chunk, selected chunk, then unselected chunk.
|
||||
|
||||
const wxString& str = stringWhole;
|
||||
|
||||
dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
|
||||
|
||||
// 1. Initial unselected chunk, if any, up until start of selection.
|
||||
@@ -7219,22 +7257,31 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
|
||||
|
||||
bool haveDescent = false;
|
||||
int startPos = range.GetStart() - GetRange().GetStart();
|
||||
long len = range.GetLength();
|
||||
|
||||
wxString str(m_text);
|
||||
wxString stringChunk;
|
||||
|
||||
{
|
||||
// We don't need stringWhole. Only prepare stringChunk.
|
||||
wxString stringWhole;
|
||||
const wxString* pWholeString = &m_text;
|
||||
if (context.HasVirtualText(this))
|
||||
{
|
||||
if (!context.GetVirtualText(this, str) || str.Length() != m_text.Length())
|
||||
str = m_text;
|
||||
if (context.GetVirtualText(this, stringWhole) && stringWhole.Length() == m_text.Length())
|
||||
pWholeString = &stringWhole;
|
||||
}
|
||||
|
||||
wxString toReplace = wxRichTextLineBreakChar;
|
||||
str.Replace(toReplace, wxT(" "));
|
||||
long len = range.GetLength();
|
||||
stringChunk = pWholeString->Mid(startPos, (size_t) len);
|
||||
|
||||
wxString stringChunk = str.Mid(startPos, (size_t) len);
|
||||
|
||||
if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||
// Replace line break characters with spaces
|
||||
wxString toRemove = wxRichTextLineBreakChar;
|
||||
stringChunk.Replace(toRemove, wxT(" "));
|
||||
if (textAttr.HasTextEffects() &&
|
||||
(textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||
{
|
||||
stringChunk.MakeUpper();
|
||||
}
|
||||
}
|
||||
|
||||
wxCoord w, h;
|
||||
int width = 0;
|
||||
|
Reference in New Issue
Block a user