Restore generic GetPartialTextExtents() version use in wxGTK and wxMSW.

Non-wxWindowDC-derived wxDC classes in wxGTK, such as wxGtkPrinterDCImpl, have
to fall back on the generic implementation of GetPartialTextExtents() as Pango
version can't be used with them.

This fixes a crash due to using NULL Pango layout when printing wxRichTextCtrl
in wxGTK.

Closes #14847.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73017 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2012-11-25 23:17:33 +00:00
parent d76774b444
commit 1cd86ff668
4 changed files with 88 additions and 70 deletions

View File

@ -198,3 +198,82 @@ bool wxTextMeasureBase::GetPartialTextExtents(const wxString& text,
return DoGetPartialTextExtents(text, widths, scaleX);
}
// ----------------------------------------------------------------------------
// Generic and inefficient DoGetPartialTextExtents() implementation.
// ----------------------------------------------------------------------------
// Each element of the widths array will be the width of the string up to and
// including the corresponding character in text. This is the generic
// implementation, the port-specific classes should do this with native APIs
// if available and if faster. Note: pango_layout_index_to_pos is much slower
// than calling GetTextExtent!!
#define FWC_SIZE 256
class FontWidthCache
{
public:
FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
~FontWidthCache() { delete []m_widths; }
void Reset()
{
if ( !m_widths )
m_widths = new int[FWC_SIZE];
memset(m_widths, 0, sizeof(int)*FWC_SIZE);
}
wxFont m_font;
double m_scaleX;
int *m_widths;
};
static FontWidthCache s_fontWidthCache;
bool wxTextMeasureBase::DoGetPartialTextExtents(const wxString& text,
wxArrayInt& widths,
double scaleX)
{
int totalWidth = 0;
// reset the cache if font or horizontal scale have changed
if ( !s_fontWidthCache.m_widths ||
!wxIsSameDouble(s_fontWidthCache.m_scaleX, scaleX) ||
(s_fontWidthCache.m_font != *m_font) )
{
s_fontWidthCache.Reset();
s_fontWidthCache.m_font = *m_font;
s_fontWidthCache.m_scaleX = scaleX;
}
// Calculate the position of each character based on the widths of
// the previous characters. This is inexact for not fixed fonts.
int n = 0;
for ( wxString::const_iterator it = text.begin();
it != text.end();
++it )
{
const wxChar c = *it;
unsigned int c_int = (unsigned int)c;
int w;
if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
{
w = s_fontWidthCache.m_widths[c_int];
}
else
{
DoGetTextExtent(c, &w, NULL);
if (c_int < FWC_SIZE)
s_fontWidthCache.m_widths[c_int] = w;
}
totalWidth += w;
widths[n++] = totalWidth;
}
return true;
}

View File

@ -59,78 +59,11 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
//else: we already asserted in the ctor, don't do it any more
}
// Each element of the widths array will be the width of the string up to and
// including the corresponding character in text. This is the generic
// implementation, the port-specific classes should do this with native APIs
// if available and if faster. Note: pango_layout_index_to_pos is much slower
// than calling GetTextExtent!!
#define FWC_SIZE 256
class FontWidthCache
{
public:
FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
~FontWidthCache() { delete []m_widths; }
void Reset()
{
if ( !m_widths )
m_widths = new int[FWC_SIZE];
memset(m_widths, 0, sizeof(int)*FWC_SIZE);
}
wxFont m_font;
double m_scaleX;
int *m_widths;
};
static FontWidthCache s_fontWidthCache;
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
wxArrayInt& widths,
double scaleX)
{
int totalWidth = 0;
// reset the cache if font or horizontal scale have changed
if ( !s_fontWidthCache.m_widths ||
!wxIsSameDouble(s_fontWidthCache.m_scaleX, scaleX) ||
(s_fontWidthCache.m_font != *m_font) )
{
s_fontWidthCache.Reset();
s_fontWidthCache.m_font = *m_font;
s_fontWidthCache.m_scaleX = scaleX;
}
// Calculate the position of each character based on the widths of
// the previous characters. This is inexact for not fixed fonts.
int n = 0;
for ( wxString::const_iterator it = text.begin();
it != text.end();
++it )
{
const wxChar c = *it;
unsigned int c_int = (unsigned int)c;
int w;
if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
{
w = s_fontWidthCache.m_widths[c_int];
}
else
{
DoGetTextExtent(c, &w, NULL);
if (c_int < FWC_SIZE)
s_fontWidthCache.m_widths[c_int] = w;
}
totalWidth += w;
widths[n++] = totalWidth;
}
return true;
return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
}
#endif // wxUSE_GENERIC_TEXTMEASURE

View File

@ -165,8 +165,11 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
wxArrayInt& widths,
double WXUNUSED(scaleX))
double scaleX)
{
if ( !m_layout )
return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
// Set layout's text
const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont());
if ( !dataUTF8 )

View File

@ -150,8 +150,11 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
wxArrayInt& widths,
double WXUNUSED(scaleX))
double scaleX)
{
if ( !m_hdc )
return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
static int maxLenText = -1;
static int maxWidth = -1;