Fix text jumps during selection dragging on MSW
When selecting the text in wxHtmlWindow by dragging the mouse the text to the right of the selection sometimes jumps horizontally. This happens only on MSW and only for TrueType fonts. The reason is that wxDC::GetPartialTextExtents() and wxDC::GetTextExtent() give different results if the text contains characters with underhangs or overhangs. Fix this by caching results of wxDC::GetPartialTextExtents() and using them instead of calling wxDC::GetTextExtent().
This commit is contained in:
committed by
Vadim Zeitlin
parent
bce4bf1c8e
commit
a7dc1c0e0f
@@ -35,7 +35,8 @@ public:
|
|||||||
wxHtmlSelection()
|
wxHtmlSelection()
|
||||||
: m_fromPos(wxDefaultPosition), m_toPos(wxDefaultPosition),
|
: m_fromPos(wxDefaultPosition), m_toPos(wxDefaultPosition),
|
||||||
m_fromCharacterPos(-1), m_toCharacterPos(-1),
|
m_fromCharacterPos(-1), m_toCharacterPos(-1),
|
||||||
m_fromCell(NULL), m_toCell(NULL) {}
|
m_fromCell(NULL), m_toCell(NULL),
|
||||||
|
m_extBeforeSel(0), m_extBeforeSelEnd(0) {}
|
||||||
|
|
||||||
// this version is used for the user selection defined with the mouse
|
// this version is used for the user selection defined with the mouse
|
||||||
void Set(const wxPoint& fromPos, const wxHtmlCell *fromCell,
|
void Set(const wxPoint& fromPos, const wxHtmlCell *fromCell,
|
||||||
@@ -58,6 +59,11 @@ public:
|
|||||||
wxCoord GetFromCharacterPos () const { return m_fromCharacterPos; }
|
wxCoord GetFromCharacterPos () const { return m_fromCharacterPos; }
|
||||||
wxCoord GetToCharacterPos () const { return m_toCharacterPos; }
|
wxCoord GetToCharacterPos () const { return m_toCharacterPos; }
|
||||||
|
|
||||||
|
void SetExtentBeforeSelection(unsigned ext) { m_extBeforeSel = ext; }
|
||||||
|
void SetExtentBeforeSelectionEnd(unsigned ext) { m_extBeforeSelEnd = ext; }
|
||||||
|
unsigned GetExtentBeforeSelection() const { return m_extBeforeSel; }
|
||||||
|
unsigned GetExtentBeforeSelectionEnd() const { return m_extBeforeSelEnd; }
|
||||||
|
|
||||||
bool IsEmpty() const
|
bool IsEmpty() const
|
||||||
{ return m_fromPos == wxDefaultPosition &&
|
{ return m_fromPos == wxDefaultPosition &&
|
||||||
m_toPos == wxDefaultPosition; }
|
m_toPos == wxDefaultPosition; }
|
||||||
@@ -66,6 +72,12 @@ private:
|
|||||||
wxPoint m_fromPos, m_toPos;
|
wxPoint m_fromPos, m_toPos;
|
||||||
wxCoord m_fromCharacterPos, m_toCharacterPos;
|
wxCoord m_fromCharacterPos, m_toCharacterPos;
|
||||||
const wxHtmlCell *m_fromCell, *m_toCell;
|
const wxHtmlCell *m_fromCell, *m_toCell;
|
||||||
|
|
||||||
|
// Extent of the text before selection start.
|
||||||
|
unsigned m_extBeforeSel;
|
||||||
|
|
||||||
|
// Extent of the text from the beginning to the selection end.
|
||||||
|
unsigned m_extBeforeSelEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -431,7 +443,8 @@ protected:
|
|||||||
void SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const;
|
void SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const;
|
||||||
void Split(const wxDC& dc,
|
void Split(const wxDC& dc,
|
||||||
const wxPoint& selFrom, const wxPoint& selTo,
|
const wxPoint& selFrom, const wxPoint& selTo,
|
||||||
unsigned& pos1, unsigned& pos2) const;
|
unsigned& pos1, unsigned& pos2,
|
||||||
|
unsigned& ext1, unsigned& ext2) const;
|
||||||
|
|
||||||
wxString m_Word;
|
wxString m_Word;
|
||||||
bool m_allowLinebreak;
|
bool m_allowLinebreak;
|
||||||
|
@@ -343,7 +343,8 @@ void wxHtmlWordCell::SetPreviousWord(wxHtmlWordCell *cell)
|
|||||||
// where s2 and s3 start:
|
// where s2 and s3 start:
|
||||||
void wxHtmlWordCell::Split(const wxDC& dc,
|
void wxHtmlWordCell::Split(const wxDC& dc,
|
||||||
const wxPoint& selFrom, const wxPoint& selTo,
|
const wxPoint& selFrom, const wxPoint& selTo,
|
||||||
unsigned& pos1, unsigned& pos2) const
|
unsigned& pos1, unsigned& pos2,
|
||||||
|
unsigned& ext1, unsigned& ext2) const
|
||||||
{
|
{
|
||||||
wxPoint pt1 = (selFrom == wxDefaultPosition) ?
|
wxPoint pt1 = (selFrom == wxDefaultPosition) ?
|
||||||
wxDefaultPosition : selFrom - GetAbsPos();
|
wxDefaultPosition : selFrom - GetAbsPos();
|
||||||
@@ -400,21 +401,30 @@ void wxHtmlWordCell::Split(const wxDC& dc,
|
|||||||
pos2 = j;
|
pos2 = j;
|
||||||
|
|
||||||
wxASSERT( pos2 >= pos1 );
|
wxASSERT( pos2 >= pos1 );
|
||||||
|
|
||||||
|
ext1 = pos1 == 0 ? 0 : (pos1 < widths.size() ? widths[pos1-1] : widths.Last());
|
||||||
|
ext2 = pos2 == 0 ? 0 : (pos2 < widths.size() ? widths[pos2-1] : widths.Last());
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const
|
void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const
|
||||||
{
|
{
|
||||||
unsigned p1, p2;
|
unsigned p1, p2, ext1, ext2;
|
||||||
|
|
||||||
Split(dc,
|
Split(dc,
|
||||||
this == s->GetFromCell() ? s->GetFromPos() : wxDefaultPosition,
|
this == s->GetFromCell() ? s->GetFromPos() : wxDefaultPosition,
|
||||||
this == s->GetToCell() ? s->GetToPos() : wxDefaultPosition,
|
this == s->GetToCell() ? s->GetToPos() : wxDefaultPosition,
|
||||||
p1, p2);
|
p1, p2, ext1, ext2);
|
||||||
|
|
||||||
if ( this == s->GetFromCell() )
|
if ( this == s->GetFromCell() )
|
||||||
|
{
|
||||||
s->SetFromCharacterPos(p1); // selection starts here
|
s->SetFromCharacterPos(p1); // selection starts here
|
||||||
|
s->SetExtentBeforeSelection(ext1);
|
||||||
|
}
|
||||||
if ( this == s->GetToCell() )
|
if ( this == s->GetToCell() )
|
||||||
|
{
|
||||||
s->SetToCharacterPos(p2); // selection ends here
|
s->SetToCharacterPos(p2); // selection ends here
|
||||||
|
s->SetExtentBeforeSelectionEnd(ext2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -459,7 +469,6 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
|
|||||||
// Selection changing, we must draw the word piecewise:
|
// Selection changing, we must draw the word piecewise:
|
||||||
wxHtmlSelection *s = info.GetSelection();
|
wxHtmlSelection *s = info.GetSelection();
|
||||||
wxString txt;
|
wxString txt;
|
||||||
int w, h;
|
|
||||||
int ofs = 0;
|
int ofs = 0;
|
||||||
|
|
||||||
// NB: this is quite a hack: in order to compute selection boundaries
|
// NB: this is quite a hack: in order to compute selection boundaries
|
||||||
@@ -479,8 +488,7 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
|
|||||||
{
|
{
|
||||||
txt = m_Word.Mid(0, part1);
|
txt = m_Word.Mid(0, part1);
|
||||||
dc.DrawText(txt, x + m_PosX, y + m_PosY);
|
dc.DrawText(txt, x + m_PosX, y + m_PosY);
|
||||||
dc.GetTextExtent(txt, &w, &h);
|
ofs += s->GetExtentBeforeSelection();
|
||||||
ofs += w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchSelState(dc, info, true);
|
SwitchSelState(dc, info, true);
|
||||||
@@ -490,11 +498,9 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y,
|
|||||||
|
|
||||||
if ( (size_t)part2 < m_Word.length() )
|
if ( (size_t)part2 < m_Word.length() )
|
||||||
{
|
{
|
||||||
dc.GetTextExtent(txt, &w, &h);
|
|
||||||
ofs += w;
|
|
||||||
SwitchSelState(dc, info, false);
|
SwitchSelState(dc, info, false);
|
||||||
txt = m_Word.Mid(part2);
|
txt = m_Word.Mid(part2);
|
||||||
dc.DrawText(txt, ofs + x + m_PosX, y + m_PosY);
|
dc.DrawText(txt, x + m_PosX + s->GetExtentBeforeSelectionEnd(), y + m_PosY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
drawSelectionAfterCell = true;
|
drawSelectionAfterCell = true;
|
||||||
|
Reference in New Issue
Block a user