X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1bce253a23047c6153e130d02e776d3d34b05793..8fdbcf4de8eeff67ccfaf3deec833d203f112629:/src/common/textmeasurecmn.cpp?ds=inline diff --git a/src/common/textmeasurecmn.cpp b/src/common/textmeasurecmn.cpp index df91ca38bd..6381059dd8 100644 --- a/src/common/textmeasurecmn.cpp +++ b/src/common/textmeasurecmn.cpp @@ -53,6 +53,13 @@ wxTextMeasureBase::wxTextMeasureBase(const wxWindow *win, const wxFont *theFont) m_useDCImpl = false; } +wxFont wxTextMeasureBase::GetFont() const +{ + return m_font ? *m_font + : m_win ? m_win->GetFont() + : m_dc->GetFont(); +} + void wxTextMeasureBase::CallGetTextExtent(const wxString& string, wxCoord *width, wxCoord *height, @@ -158,18 +165,15 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text, *heightOneLine = heightLine; } -void wxTextMeasureBase::GetLargestStringExtent(const wxVector& strings, - wxCoord *width, - wxCoord *height) +wxSize wxTextMeasureBase::GetLargestStringExtent(size_t n, + const wxString* strings) { MeasuringGuard guard(*this); wxCoord w, h, widthMax = 0, heightMax = 0; - for ( wxVector::const_iterator i = strings.begin(); - i != strings.end(); - ++i ) + for ( size_t i = 0; i < n; ++i ) { - CallGetTextExtent(*i, &w, &h); + CallGetTextExtent(strings[i], &w, &h); if ( w > widthMax ) widthMax = w; @@ -177,10 +181,7 @@ void wxTextMeasureBase::GetLargestStringExtent(const wxVector& strings heightMax = h; } - if ( width ) - *width = widthMax; - if ( height ) - *height = heightMax; + return wxSize(widthMax, heightMax); } bool wxTextMeasureBase::GetPartialTextExtents(const wxString& text, @@ -197,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; +} +