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:
@@ -198,3 +198,82 @@ bool wxTextMeasureBase::GetPartialTextExtents(const wxString& text,
|
|||||||
|
|
||||||
return DoGetPartialTextExtents(text, widths, scaleX);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -59,78 +59,11 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
|
|||||||
//else: we already asserted in the ctor, don't do it any more
|
//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,
|
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
|
||||||
wxArrayInt& widths,
|
wxArrayInt& widths,
|
||||||
double scaleX)
|
double scaleX)
|
||||||
{
|
{
|
||||||
int totalWidth = 0;
|
return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_GENERIC_TEXTMEASURE
|
#endif // wxUSE_GENERIC_TEXTMEASURE
|
||||||
|
@@ -165,8 +165,11 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
|
|||||||
|
|
||||||
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
|
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
|
||||||
wxArrayInt& widths,
|
wxArrayInt& widths,
|
||||||
double WXUNUSED(scaleX))
|
double scaleX)
|
||||||
{
|
{
|
||||||
|
if ( !m_layout )
|
||||||
|
return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
|
||||||
|
|
||||||
// Set layout's text
|
// Set layout's text
|
||||||
const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont());
|
const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont());
|
||||||
if ( !dataUTF8 )
|
if ( !dataUTF8 )
|
||||||
|
@@ -150,8 +150,11 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
|
|||||||
|
|
||||||
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
|
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
|
||||||
wxArrayInt& widths,
|
wxArrayInt& widths,
|
||||||
double WXUNUSED(scaleX))
|
double scaleX)
|
||||||
{
|
{
|
||||||
|
if ( !m_hdc )
|
||||||
|
return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
|
||||||
|
|
||||||
static int maxLenText = -1;
|
static int maxLenText = -1;
|
||||||
static int maxWidth = -1;
|
static int maxWidth = -1;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user