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