]> git.saurik.com Git - wxWidgets.git/blob - src/common/textmeasurecmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / textmeasurecmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/textmeasurecmn.cpp
3 // Purpose: wxTextMeasureBase implementation
4 // Author: Manuel Martin
5 // Created: 2012-10-05
6 // RCS-ID: $Id:
7 // Copyright: (c) 1997-2012 wxWidgets team
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/dc.h"
24 #include "wx/window.h"
25 #endif //WX_PRECOMP
26
27 #include "wx/private/textmeasure.h"
28
29 // ============================================================================
30 // wxTextMeasureBase implementation
31 // ============================================================================
32
33 wxTextMeasureBase::wxTextMeasureBase(const wxDC *dc, const wxFont *theFont)
34 : m_dc(dc),
35 m_win(NULL),
36 m_font(theFont)
37 {
38 wxASSERT_MSG( dc, wxS("wxTextMeasure needs a valid wxDC") );
39
40 // By default, use wxDC version, we'll explicitly reset this to false in
41 // the derived classes if the DC is of native variety.
42 m_useDCImpl = true;
43 }
44
45 wxTextMeasureBase::wxTextMeasureBase(const wxWindow *win, const wxFont *theFont)
46 : m_dc(NULL),
47 m_win(win),
48 m_font(theFont)
49 {
50 wxASSERT_MSG( win, wxS("wxTextMeasure needs a valid wxWindow") );
51
52 // We don't have any wxDC so we can't forward to it.
53 m_useDCImpl = false;
54 }
55
56 wxFont wxTextMeasureBase::GetFont() const
57 {
58 return m_font ? *m_font
59 : m_win ? m_win->GetFont()
60 : m_dc->GetFont();
61 }
62
63 void wxTextMeasureBase::CallGetTextExtent(const wxString& string,
64 wxCoord *width,
65 wxCoord *height,
66 wxCoord *descent,
67 wxCoord *externalLeading)
68 {
69 if ( m_useDCImpl )
70 m_dc->GetTextExtent(string, width, height, descent, externalLeading);
71 else
72 DoGetTextExtent(string, width, height, descent, externalLeading);
73 }
74
75 void wxTextMeasureBase::GetTextExtent(const wxString& string,
76 wxCoord *width,
77 wxCoord *height,
78 wxCoord *descent,
79 wxCoord *externalLeading)
80 {
81 // To make the code simpler, make sure that the width and height pointers
82 // are always valid, even if they point to dummy variables.
83 int unusedWidth, unusedHeight;
84 if ( !width )
85 width = &unusedWidth;
86 if ( !height )
87 height = &unusedHeight;
88
89 if ( string.empty() )
90 {
91 *width =
92 *height = 0;
93
94 return;
95 }
96
97 MeasuringGuard guard(*this);
98
99 CallGetTextExtent(string, width, height, descent, externalLeading);
100 }
101
102 void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
103 wxCoord *width,
104 wxCoord *height,
105 wxCoord *heightOneLine)
106 {
107 MeasuringGuard guard(*this);
108
109 wxCoord widthTextMax = 0, widthLine,
110 heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
111
112 wxString curLine;
113 for ( wxString::const_iterator pc = text.begin(); ; ++pc )
114 {
115 if ( pc == text.end() || *pc == wxS('\n') )
116 {
117 if ( curLine.empty() )
118 {
119 // we can't use GetTextExtent - it will return 0 for both width
120 // and height and an empty line should count in height
121 // calculation
122
123 // assume that this line has the same height as the previous
124 // one
125 if ( !heightLineDefault )
126 heightLineDefault = heightLine;
127
128 if ( !heightLineDefault )
129 {
130 // but we don't know it yet - choose something reasonable
131 int dummy;
132 CallGetTextExtent(wxS("W"), &dummy, &heightLineDefault);
133 }
134
135 heightTextTotal += heightLineDefault;
136 }
137 else
138 {
139 CallGetTextExtent(curLine, &widthLine, &heightLine);
140 if ( widthLine > widthTextMax )
141 widthTextMax = widthLine;
142 heightTextTotal += heightLine;
143 }
144
145 if ( pc == text.end() )
146 {
147 break;
148 }
149 else // '\n'
150 {
151 curLine.clear();
152 }
153 }
154 else
155 {
156 curLine += *pc;
157 }
158 }
159
160 if ( width )
161 *width = widthTextMax;
162 if ( height )
163 *height = heightTextTotal;
164 if ( heightOneLine )
165 *heightOneLine = heightLine;
166 }
167
168 wxSize wxTextMeasureBase::GetLargestStringExtent(size_t n,
169 const wxString* strings)
170 {
171 MeasuringGuard guard(*this);
172
173 wxCoord w, h, widthMax = 0, heightMax = 0;
174 for ( size_t i = 0; i < n; ++i )
175 {
176 CallGetTextExtent(strings[i], &w, &h);
177
178 if ( w > widthMax )
179 widthMax = w;
180 if ( h > heightMax )
181 heightMax = h;
182 }
183
184 return wxSize(widthMax, heightMax);
185 }
186
187 bool wxTextMeasureBase::GetPartialTextExtents(const wxString& text,
188 wxArrayInt& widths,
189 double scaleX)
190 {
191 widths.Empty();
192 if ( text.empty() )
193 return true;
194
195 MeasuringGuard guard(*this);
196
197 widths.Add(0, text.length());
198
199 return DoGetPartialTextExtents(text, widths, scaleX);
200 }