#define wxRICHTEXT_FORMATTED 0x01
#define wxRICHTEXT_UNFORMATTED 0x02
+#define wxRICHTEXT_CACHE_SIZE 0x04
/*!
* Flags for SetStyle/SetListStyle
#define wxSCRIPT_MUL_FACTOR 1.5
+// Leave on for faster drawing, by storing the length of each object in a line
+#define wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING 1
+
/*!
* wxRichTextFontTable
* Manages quick access to a pool of fonts for rendering rich text
void SetDescent(int descent) { m_descent = descent; }
int GetDescent() const { return m_descent; }
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+ wxArrayInt& GetObjectSizes() { return m_objectSizes; }
+ const wxArrayInt& GetObjectSizes() const { return m_objectSizes; }
+#endif
+
// Operations
/// Initialisation
// The parent object
wxRichTextParagraph* m_parent;
+
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+ wxArrayInt m_objectSizes;
+#endif
};
WX_DECLARE_LIST_WITH_DECL( wxRichTextLine, wxRichTextLineList , class WXDLLIMPEXP_RICHTEXT );
// Loop through objects until we get to the one within range
wxRichTextObjectList::compatibility_iterator node2 = m_children.GetFirst();
+
+ int i = 0;
while (node2)
{
wxRichTextObject* child = node2->GetData();
objectRange.LimitTo(lineRange);
wxSize objectSize;
- int descent = 0;
- child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED, objectPosition);
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING && wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS
+ if (i < (int) line->GetObjectSizes().GetCount())
+ {
+ objectSize.x = line->GetObjectSizes()[(size_t) i];
+ }
+ else
+#endif
+ {
+ int descent = 0;
+ child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED, objectPosition);
+ }
// Use the child object's width, but the whole line's height
wxRect childRect(objectPosition, wxSize(objectSize.x, line->GetSize().y));
child->Draw(dc, objectRange, selectionRange, childRect, maxDescent, style);
objectPosition.x += objectSize.x;
+ i ++;
}
else if (child->GetRange().GetStart() > lineRange.GetEnd())
// Can break out of inner loop now since we've passed this line's range
int lineCount = 0;
- wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
+ wxRichTextObjectList::compatibility_iterator node;
+
+#if wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS
+ wxUnusedVar(style);
+ wxArrayInt partialExtents;
+
+ wxSize paraSize;
+ int paraDescent;
+
+ // This calculates the partial text extents
+ GetRangeSize(GetRange(), paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, wxPoint(0,0), & partialExtents);
+#else
+ node = m_children.GetFirst();
while (node)
{
wxRichTextObject* child = node->GetData();
node = node->GetNext();
}
-#if wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS
- wxArrayInt partialExtents;
-
- wxSize paraSize;
- int paraDescent;
-
- // This calculates the partial text extents
- GetRangeSize(GetRange(), paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED, wxPoint(0,0), & partialExtents);
#endif
// Split up lines
m_dirty = false;
+#if wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+ // Use the text extents to calculate the size of each fragment in each line
+ wxRichTextLineList::compatibility_iterator lineNode = m_cachedLines.GetFirst();
+ while (lineNode)
+ {
+ wxRichTextLine* line = lineNode->GetData();
+ wxRichTextRange lineRange = line->GetAbsoluteRange();
+
+ // Loop through objects until we get to the one within range
+ wxRichTextObjectList::compatibility_iterator node2 = m_children.GetFirst();
+
+ while (node2)
+ {
+ wxRichTextObject* child = node2->GetData();
+
+ if (!child->GetRange().IsOutside(lineRange))
+ {
+ wxRichTextRange rangeToUse = lineRange;
+ rangeToUse.LimitTo(child->GetRange());
+
+ // Find the size of the child from the text extents, and store in an array
+ // for drawing later
+ int left = 0;
+ if (rangeToUse.GetStart() > GetRange().GetStart())
+ left = partialExtents[(rangeToUse.GetStart()-1) - GetRange().GetStart()];
+ int right = partialExtents[rangeToUse.GetEnd() - GetRange().GetStart()];
+ int sz = right - left;
+ line->GetObjectSizes().Add(sz);
+ }
+ else if (child->GetRange().GetStart() > lineRange.GetEnd())
+ // Can break out of inner loop now since we've passed this line's range
+ break;
+
+ node2 = node2->GetNext();
+ }
+
+ lineNode = lineNode->GetNext();
+ }
+#endif
+#endif
+
return true;
}
sz.x += childSize.x;
descent = wxMax(descent, childDescent);
+ if ((flags & wxRICHTEXT_CACHE_SIZE) && (rangeToUse == child->GetRange()))
+ {
+ child->SetCachedSize(childSize);
+ child->SetDescent(childDescent);
+ }
+
if (partialExtents)
{
int lastSize;
}
else
{
+#if wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS
+ wxArrayInt partialExtents;
+
+ wxSize paraSize;
+ int paraDescent;
+
+ // This calculates the partial text extents
+ GetRangeSize(lineRange, paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED, wxPoint(0,0), & partialExtents);
+
+ int lastX = linePos.x;
+ size_t i;
+ for (i = 0; i < partialExtents.GetCount(); i++)
+ {
+ int nextX = partialExtents[i] + linePos.x;
+
+ if (pt.x >= lastX && pt.x <= nextX)
+ {
+ textPosition = i + lineRange.GetStart(); // minus 1?
+
+ // So now we know it's between i-1 and i.
+ // Let's see if we can be more precise about
+ // which side of the position it's on.
+
+ int midPoint = (nextX - lastX)/2 + lastX;
+ if (pt.x >= midPoint)
+ return wxRICHTEXT_HITTEST_AFTER;
+ else
+ return wxRICHTEXT_HITTEST_BEFORE;
+ }
+
+ lastX = nextX;
+ }
+#else
long i;
int lastX = linePos.x;
for (i = lineRange.GetStart(); i <= lineRange.GetEnd(); i++)
lastX = nextX;
}
}
+#endif
}
}
m_pos = wxPoint(0, 0);
m_size = wxSize(0, 0);
m_descent = 0;
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+ m_objectSizes.Clear();
+#endif
}
/// Copy
void wxRichTextLine::Copy(const wxRichTextLine& obj)
{
m_range = obj.m_range;
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+ m_objectSizes = obj.m_objectSizes;
+#endif
}
/// Get the absolute object position