1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/textmeasurecmn.cpp
3 // Purpose: wxTextMeasureBase implementation
4 // Author: Manuel Martin
6 // Copyright: (c) 1997-2012 wxWidgets team
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
23 #include "wx/window.h"
26 #include "wx/private/textmeasure.h"
28 // ============================================================================
29 // wxTextMeasureBase implementation
30 // ============================================================================
32 wxTextMeasureBase::wxTextMeasureBase(const wxDC
*dc
, const wxFont
*theFont
)
37 wxASSERT_MSG( dc
, wxS("wxTextMeasure needs a valid wxDC") );
39 // By default, use wxDC version, we'll explicitly reset this to false in
40 // the derived classes if the DC is of native variety.
44 wxTextMeasureBase::wxTextMeasureBase(const wxWindow
*win
, const wxFont
*theFont
)
49 wxASSERT_MSG( win
, wxS("wxTextMeasure needs a valid wxWindow") );
51 // We don't have any wxDC so we can't forward to it.
55 wxFont
wxTextMeasureBase::GetFont() const
57 return m_font
? *m_font
58 : m_win
? m_win
->GetFont()
62 void wxTextMeasureBase::CallGetTextExtent(const wxString
& string
,
66 wxCoord
*externalLeading
)
69 m_dc
->GetTextExtent(string
, width
, height
, descent
, externalLeading
);
71 DoGetTextExtent(string
, width
, height
, descent
, externalLeading
);
74 void wxTextMeasureBase::GetTextExtent(const wxString
& string
,
78 wxCoord
*externalLeading
)
80 // To make the code simpler, make sure that the width and height pointers
81 // are always valid, even if they point to dummy variables.
82 int unusedWidth
, unusedHeight
;
86 height
= &unusedHeight
;
88 // Avoid even setting up the DC for measuring if we don't actually need to
90 if ( string
.empty() && !descent
&& !externalLeading
)
98 MeasuringGuard
guard(*this);
100 CallGetTextExtent(string
, width
, height
, descent
, externalLeading
);
103 void wxTextMeasureBase::GetMultiLineTextExtent(const wxString
& text
,
106 wxCoord
*heightOneLine
)
108 MeasuringGuard
guard(*this);
110 wxCoord widthTextMax
= 0, widthLine
,
111 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
114 for ( wxString::const_iterator pc
= text
.begin(); ; ++pc
)
116 if ( pc
== text
.end() || *pc
== wxS('\n') )
118 if ( curLine
.empty() )
120 // we can't use GetTextExtent - it will return 0 for both width
121 // and height and an empty line should count in height
124 // assume that this line has the same height as the previous
126 if ( !heightLineDefault
)
127 heightLineDefault
= heightLine
;
129 if ( !heightLineDefault
)
131 // but we don't know it yet - choose something reasonable
133 CallGetTextExtent(wxS("W"), &dummy
, &heightLineDefault
);
136 heightTextTotal
+= heightLineDefault
;
140 CallGetTextExtent(curLine
, &widthLine
, &heightLine
);
141 if ( widthLine
> widthTextMax
)
142 widthTextMax
= widthLine
;
143 heightTextTotal
+= heightLine
;
146 if ( pc
== text
.end() )
162 *width
= widthTextMax
;
164 *height
= heightTextTotal
;
166 *heightOneLine
= heightLine
;
169 wxSize
wxTextMeasureBase::GetLargestStringExtent(size_t n
,
170 const wxString
* strings
)
172 MeasuringGuard
guard(*this);
174 wxCoord w
, h
, widthMax
= 0, heightMax
= 0;
175 for ( size_t i
= 0; i
< n
; ++i
)
177 CallGetTextExtent(strings
[i
], &w
, &h
);
185 return wxSize(widthMax
, heightMax
);
188 bool wxTextMeasureBase::GetPartialTextExtents(const wxString
& text
,
196 MeasuringGuard
guard(*this);
198 widths
.Add(0, text
.length());
200 return DoGetPartialTextExtents(text
, widths
, scaleX
);
203 // ----------------------------------------------------------------------------
204 // Generic and inefficient DoGetPartialTextExtents() implementation.
205 // ----------------------------------------------------------------------------
207 // Each element of the widths array will be the width of the string up to and
208 // including the corresponding character in text. This is the generic
209 // implementation, the port-specific classes should do this with native APIs
210 // if available and if faster. Note: pango_layout_index_to_pos is much slower
211 // than calling GetTextExtent!!
218 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
219 ~FontWidthCache() { delete []m_widths
; }
224 m_widths
= new int[FWC_SIZE
];
226 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
234 static FontWidthCache s_fontWidthCache
;
236 bool wxTextMeasureBase::DoGetPartialTextExtents(const wxString
& text
,
242 // reset the cache if font or horizontal scale have changed
243 if ( !s_fontWidthCache
.m_widths
||
244 !wxIsSameDouble(s_fontWidthCache
.m_scaleX
, scaleX
) ||
245 (s_fontWidthCache
.m_font
!= *m_font
) )
247 s_fontWidthCache
.Reset();
248 s_fontWidthCache
.m_font
= *m_font
;
249 s_fontWidthCache
.m_scaleX
= scaleX
;
252 // Calculate the position of each character based on the widths of
253 // the previous characters. This is inexact for not fixed fonts.
255 for ( wxString::const_iterator it
= text
.begin();
259 const wxChar c
= *it
;
260 unsigned int c_int
= (unsigned int)c
;
263 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
265 w
= s_fontWidthCache
.m_widths
[c_int
];
269 DoGetTextExtent(c
, &w
, NULL
);
270 if (c_int
< FWC_SIZE
)
271 s_fontWidthCache
.m_widths
[c_int
] = w
;
275 widths
[n
++] = totalWidth
;